From b07deb3fc1f54bd700a66df573bfcbc4bcc1d787 Mon Sep 17 00:00:00 2001 From: Artem Strygin Date: Thu, 2 Aug 2018 11:01:08 +0000 Subject: Rework of CPDF_Parser::GetLastObjNum. Change-Id: I0481774858a9d9823580e1207807e35be8a9eea9 Reviewed-on: https://pdfium-review.googlesource.com/36270 Reviewed-by: Lei Zhang Commit-Queue: Art Snake --- core/fpdfapi/parser/cpdf_cross_ref_table.cpp | 35 ++++++++++++++++++++++------ core/fpdfapi/parser/cpdf_cross_ref_table.h | 7 +++++- core/fpdfapi/parser/cpdf_parser.cpp | 12 ++++------ core/fpdfapi/parser/cpdf_parser.h | 2 +- 4 files changed, 40 insertions(+), 16 deletions(-) (limited to 'core/fpdfapi/parser') diff --git a/core/fpdfapi/parser/cpdf_cross_ref_table.cpp b/core/fpdfapi/parser/cpdf_cross_ref_table.cpp index 77c0e8136c..d25c5e0167 100644 --- a/core/fpdfapi/parser/cpdf_cross_ref_table.cpp +++ b/core/fpdfapi/parser/cpdf_cross_ref_table.cpp @@ -4,11 +4,21 @@ #include "core/fpdfapi/parser/cpdf_cross_ref_table.h" +#include #include #include "core/fpdfapi/parser/cpdf_dictionary.h" +#include "core/fpdfapi/parser/cpdf_number.h" #include "core/fpdfapi/parser/cpdf_parser.h" +namespace { + +constexpr char kXRefStm[] = "XRefStm"; +constexpr char kPrev[] = "Prev"; +constexpr char kSize[] = "Size"; + +} // namespace + // static std::unique_ptr CPDF_CrossRefTable::MergeUp( std::unique_ptr current, @@ -102,16 +112,24 @@ void CPDF_CrossRefTable::Update( UpdateTrailer(std::move(new_cross_ref->trailer_)); } -void CPDF_CrossRefTable::ShrinkObjectMap(uint32_t objnum) { - if (objnum == 0) { +void CPDF_CrossRefTable::ShrinkObjectMap(uint32_t max_size) { + if (max_size == 0) { objects_info_.clear(); return; } - objects_info_.erase(objects_info_.lower_bound(objnum), objects_info_.end()); + objects_info_.erase(objects_info_.lower_bound(max_size), objects_info_.end()); +} + +uint32_t CPDF_CrossRefTable::GetSize() const { + const uint32_t size_from_objects_num = + objects_info_.empty() ? 0 : (objects_info_.rbegin()->first + 1); + const int size_from_trailer = trailer() ? trailer()->GetIntegerFor(kSize) : 0; + if (size_from_trailer <= 0) + return size_from_objects_num; - if (!pdfium::ContainsKey(objects_info_, objnum - 1)) - objects_info_[objnum - 1].pos = 0; + return std::max(static_cast(size_from_trailer), + size_from_objects_num); } void CPDF_CrossRefTable::UpdateInfo( @@ -149,8 +167,11 @@ void CPDF_CrossRefTable::UpdateTrailer( return; } - new_trailer->SetFor("XRefStm", trailer_->RemoveFor("XRefStm")); - new_trailer->SetFor("Prev", trailer_->RemoveFor("Prev")); + new_trailer->RemoveFor(kXRefStm); + new_trailer->RemoveFor(kPrev); + new_trailer->SetNewFor( + kSize, std::max(trailer_->GetIntegerFor(kSize), + new_trailer->GetIntegerFor(kSize))); for (auto it = new_trailer->begin(); it != new_trailer->end();) { const ByteString key = it->first; diff --git a/core/fpdfapi/parser/cpdf_cross_ref_table.h b/core/fpdfapi/parser/cpdf_cross_ref_table.h index 9631216b0c..d8bda7125f 100644 --- a/core/fpdfapi/parser/cpdf_cross_ref_table.h +++ b/core/fpdfapi/parser/cpdf_cross_ref_table.h @@ -60,7 +60,12 @@ class CPDF_CrossRefTable { void Update(std::unique_ptr new_cross_ref); - void ShrinkObjectMap(uint32_t objnum); + void ShrinkObjectMap(uint32_t max_size); + + // The total number of entries in the file’s cross-reference table, as + // defined by the combination of the original section and all update + // section. + uint32_t GetSize() const; private: void UpdateInfo(std::map&& new_objects_info); diff --git a/core/fpdfapi/parser/cpdf_parser.cpp b/core/fpdfapi/parser/cpdf_parser.cpp index e93f293f84..cb262bd1eb 100644 --- a/core/fpdfapi/parser/cpdf_parser.cpp +++ b/core/fpdfapi/parser/cpdf_parser.cpp @@ -72,9 +72,8 @@ CPDF_Parser::~CPDF_Parser() { } uint32_t CPDF_Parser::GetLastObjNum() const { - return m_CrossRefTable->objects_info().empty() - ? 0 - : m_CrossRefTable->objects_info().rbegin()->first; + const uint32_t size = m_CrossRefTable->GetSize(); + return size ? size - 1 : 0; } bool CPDF_Parser::IsValidObjectNumber(uint32_t objnum) const { @@ -115,8 +114,8 @@ bool CPDF_Parser::IsObjectFree(uint32_t objnum) const { return GetObjectType(objnum) == ObjectType::kFree; } -void CPDF_Parser::ShrinkObjectMap(uint32_t objnum) { - m_CrossRefTable->ShrinkObjectMap(objnum); +void CPDF_Parser::ShrinkObjectMap(uint32_t max_size) { + m_CrossRefTable->ShrinkObjectMap(max_size); } bool CPDF_Parser::InitSyntaxParser( @@ -746,8 +745,7 @@ bool CPDF_Parser::LoadCrossRefV5(FX_FILESIZE* pos, bool bMainXRef) { const uint8_t* segstart = pData + segindex * totalWidth; FX_SAFE_UINT32 dwMaxObjNum = startnum; dwMaxObjNum += count; - uint32_t dwV5Size = - m_CrossRefTable->objects_info().empty() ? 0 : GetLastObjNum() + 1; + uint32_t dwV5Size = m_CrossRefTable->GetSize(); if (!dwMaxObjNum.IsValid() || dwMaxObjNum.ValueOrDie() > dwV5Size) continue; diff --git a/core/fpdfapi/parser/cpdf_parser.h b/core/fpdfapi/parser/cpdf_parser.h index c07c932cf4..81d23e65b9 100644 --- a/core/fpdfapi/parser/cpdf_parser.h +++ b/core/fpdfapi/parser/cpdf_parser.h @@ -145,7 +145,7 @@ class CPDF_Parser { Error LoadLinearizedMainXRefTable(); const CPDF_ObjectStream* GetObjectStream(uint32_t object_number); std::unique_ptr ParseLinearizedHeader(); - void ShrinkObjectMap(uint32_t size); + void ShrinkObjectMap(uint32_t max_size); // A simple check whether the cross reference table matches with // the objects. bool VerifyCrossRefV4(); -- cgit v1.2.3