From d4fb57a4e23ccc2e374c64ea5d5705f492fdd083 Mon Sep 17 00:00:00 2001 From: Nicolas Pena Date: Wed, 28 Jun 2017 14:39:28 -0400 Subject: Keep all trailers in CPDF_Parser in m_Trailers MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This CL removes m_pTrailer in favor of having them all in a vector, and having an index that points to the position of the previous m_pTrailer in the vector. Bug: pdfium:787 Change-Id: Ieebbf4849f7ea78f8f74d188e3adb3446a53482e Reviewed-on: https://pdfium-review.googlesource.com/7040 Reviewed-by: dsinclair Commit-Queue: Nicolás Peña --- core/fpdfapi/parser/cpdf_parser.cpp | 89 ++++++++++++++++++++----------------- core/fpdfapi/parser/cpdf_parser.h | 10 ++++- 2 files changed, 55 insertions(+), 44 deletions(-) diff --git a/core/fpdfapi/parser/cpdf_parser.cpp b/core/fpdfapi/parser/cpdf_parser.cpp index b2bde8d242..841bf2778a 100644 --- a/core/fpdfapi/parser/cpdf_parser.cpp +++ b/core/fpdfapi/parser/cpdf_parser.cpp @@ -52,14 +52,14 @@ int32_t GetStreamFirst(const CFX_RetainPtr& pObjStream) { } // namespace CPDF_Parser::CPDF_Parser() - : m_bHasParsed(false), + : m_pSyntax(pdfium::MakeUnique()), + m_bHasParsed(false), m_bXRefStream(false), m_bVersionUpdated(false), m_FileVersion(0), m_pEncryptDict(nullptr), - m_dwXrefStartObjNum(0) { - m_pSyntax = pdfium::MakeUnique(); -} + m_TrailerPos(CPDF_Parser::kInvalidPos), + m_dwXrefStartObjNum(0) {} CPDF_Parser::~CPDF_Parser() { ReleaseEncryptHandler(); @@ -219,12 +219,13 @@ CPDF_Parser::Error CPDF_Parser::StartParse( } return SUCCESS; } + CPDF_Parser::Error CPDF_Parser::SetEncryptHandler() { ReleaseEncryptHandler(); - if (!m_pTrailer) + if (!GetTrailer()) return FORMAT_ERROR; - CPDF_Object* pEncryptObj = m_pTrailer->GetObjectFor("Encrypt"); + CPDF_Object* pEncryptObj = GetTrailer()->GetObjectFor("Encrypt"); if (pEncryptObj) { if (CPDF_Dictionary* pEncryptDict = pEncryptObj->AsDictionary()) { SetEncryptDictionary(pEncryptDict); @@ -304,11 +305,13 @@ bool CPDF_Parser::LoadAllCrossRefV4(FX_FILESIZE xrefpos) { if (!LoadCrossRefV4(xrefpos, 0, true)) return false; - m_pTrailer = LoadTrailerV4(); - if (!m_pTrailer) + std::unique_ptr trailer = LoadTrailerV4(); + if (!trailer) return false; - int32_t xrefsize = GetDirectInteger(m_pTrailer.get(), "Size"); + m_Trailers.push_back(std::move(trailer)); + m_TrailerPos = m_Trailers.size() - 1; + int32_t xrefsize = GetDirectInteger(GetTrailer(), "Size"); if (xrefsize > 0 && xrefsize <= kMaxXRefSize) ShrinkObjectMap(xrefsize); @@ -317,12 +320,12 @@ bool CPDF_Parser::LoadAllCrossRefV4(FX_FILESIZE xrefpos) { std::set seen_xrefpos; CrossRefList.push_back(xrefpos); - XRefStreamList.push_back(GetDirectInteger(m_pTrailer.get(), "XRefStm")); + XRefStreamList.push_back(GetDirectInteger(GetTrailer(), "XRefStm")); seen_xrefpos.insert(xrefpos); - // When |m_pTrailer| doesn't have Prev entry or Prev entry value is not + // When the trailer doesn't have Prev entry or Prev entry value is not // numerical, GetDirectInteger() returns 0. Loading will end. - xrefpos = GetDirectInteger(m_pTrailer.get(), "Prev"); + xrefpos = GetDirectInteger(GetTrailer(), "Prev"); while (xrefpos) { // Check for circular references. if (pdfium::ContainsKey(seen_xrefpos, xrefpos)) @@ -360,14 +363,13 @@ bool CPDF_Parser::LoadLinearizedAllCrossRefV4(FX_FILESIZE xrefpos, if (!LoadLinearizedCrossRefV4(xrefpos, dwObjCount)) return false; - if (m_pTrailer) - m_Trailers.push_back(std::move(m_pTrailer)); - - m_pTrailer = LoadTrailerV4(); - if (!m_pTrailer) + std::unique_ptr trailer = LoadTrailerV4(); + if (!trailer) return false; - int32_t xrefsize = GetDirectInteger(m_pTrailer.get(), "Size"); + m_Trailers.push_back(std::move(trailer)); + m_TrailerPos = m_Trailers.size() - 1; + int32_t xrefsize = GetDirectInteger(GetTrailer(), "Size"); if (xrefsize == 0) return false; @@ -376,10 +378,10 @@ bool CPDF_Parser::LoadLinearizedAllCrossRefV4(FX_FILESIZE xrefpos, std::set seen_xrefpos; CrossRefList.push_back(xrefpos); - XRefStreamList.push_back(GetDirectInteger(m_pTrailer.get(), "XRefStm")); + XRefStreamList.push_back(GetDirectInteger(GetTrailer(), "XRefStm")); seen_xrefpos.insert(xrefpos); - xrefpos = GetDirectInteger(m_pTrailer.get(), "Prev"); + xrefpos = GetDirectInteger(GetTrailer(), "Prev"); while (xrefpos) { // Check for circular references. if (pdfium::ContainsKey(seen_xrefpos, xrefpos)) @@ -568,7 +570,8 @@ bool CPDF_Parser::LoadAllCrossRefV5(FX_FILESIZE xrefpos) { bool CPDF_Parser::RebuildCrossRef() { m_ObjectInfo.clear(); m_SortedOffset.clear(); - m_pTrailer.reset(); + m_Trailers.clear(); + m_TrailerPos = CPDF_Parser::kInvalidPos; ParserState state = ParserState::kDefault; int32_t inside_index = 0; @@ -729,7 +732,8 @@ bool CPDF_Parser::RebuildCrossRef() { CPDF_Object* pRoot = pDict->GetObjectFor("Root"); if (pRoot && pRoot->GetDict() && pRoot->GetDict()->GetObjectFor("Pages")) { - m_pTrailer = ToDictionary(pDict->Clone()); + m_Trailers.push_back(ToDictionary(pDict->Clone())); + m_TrailerPos = m_Trailers.size() - 1; } } } @@ -785,7 +789,7 @@ bool CPDF_Parser::RebuildCrossRef() { CPDF_Stream* pStream = pObj->AsStream(); if (CPDF_Dictionary* pTrailer = pStream ? pStream->GetDict() : pObj->AsDictionary()) { - if (m_pTrailer) { + if (GetTrailer()) { CPDF_Object* pRoot = pTrailer->GetObjectFor("Root"); CPDF_Reference* pRef = ToReference(pRoot); if (!pRoot || @@ -799,19 +803,19 @@ bool CPDF_Parser::RebuildCrossRef() { uint32_t dwObjNum = pElement ? pElement->GetObjNum() : 0; if (dwObjNum) { - m_pTrailer->SetNewFor( + GetTrailer()->SetNewFor( key, m_pDocument.Get(), dwObjNum); } else { - m_pTrailer->SetFor(key, pElement->Clone()); + GetTrailer()->SetFor(key, pElement->Clone()); } } } } else { - if (pObj->IsStream()) { - m_pTrailer = ToDictionary(pTrailer->Clone()); - } else { - m_pTrailer = ToDictionary(std::move(pObj)); - } + if (pObj->IsStream()) + m_Trailers.push_back(ToDictionary(pTrailer->Clone())); + else + m_Trailers.push_back(ToDictionary(std::move(pObj))); + m_TrailerPos = m_Trailers.size() - 1; FX_FILESIZE dwSavePos = m_pSyntax->GetPos(); CFX_ByteString strWord = m_pSyntax->GetKeyword(); @@ -915,7 +919,7 @@ bool CPDF_Parser::RebuildCrossRef() { last_trailer = m_pSyntax->m_FileLen; m_SortedOffset.insert(last_trailer - m_pSyntax->m_HeaderOffset); - return m_pTrailer && !m_ObjectInfo.empty(); + return GetTrailer() && !m_ObjectInfo.empty(); } bool CPDF_Parser::LoadCrossRefV5(FX_FILESIZE* pos, bool bMainXRef) { @@ -951,7 +955,8 @@ bool CPDF_Parser::LoadCrossRefV5(FX_FILESIZE* pos, bool bMainXRef) { std::unique_ptr pNewTrailer = ToDictionary(pDict->Clone()); if (bMainXRef) { - m_pTrailer = std::move(pNewTrailer); + m_Trailers.push_back(std::move(pNewTrailer)); + m_TrailerPos = m_Trailers.size() - 1; ShrinkObjectMap(size); for (auto& it : m_ObjectInfo) it.second.type = 0; @@ -1060,10 +1065,10 @@ bool CPDF_Parser::LoadCrossRefV5(FX_FILESIZE* pos, bool bMainXRef) { } CPDF_Array* CPDF_Parser::GetIDArray() { - if (!m_pTrailer) + if (!GetTrailer()) return nullptr; - CPDF_Object* pID = m_pTrailer->GetObjectFor("ID"); + CPDF_Object* pID = GetTrailer()->GetObjectFor("ID"); if (!pID) return nullptr; @@ -1074,19 +1079,19 @@ CPDF_Array* CPDF_Parser::GetIDArray() { std::unique_ptr pNewObj = ParseIndirectObject(nullptr, pRef->GetRefObjNum()); pID = pNewObj.get(); - m_pTrailer->SetFor("ID", std::move(pNewObj)); + GetTrailer()->SetFor("ID", std::move(pNewObj)); return ToArray(pID); } uint32_t CPDF_Parser::GetRootObjNum() { CPDF_Reference* pRef = - ToReference(m_pTrailer ? m_pTrailer->GetObjectFor("Root") : nullptr); + ToReference(GetTrailer() ? GetTrailer()->GetObjectFor("Root") : nullptr); return pRef ? pRef->GetRefObjNum() : 0; } uint32_t CPDF_Parser::GetInfoObjNum() { CPDF_Reference* pRef = - ToReference(m_pTrailer ? m_pTrailer->GetObjectFor("Info") : nullptr); + ToReference(GetTrailer() ? GetTrailer()->GetObjectFor("Info") : nullptr); if (pRef) return pRef->GetRefObjNum(); @@ -1488,11 +1493,13 @@ CPDF_Parser::Error CPDF_Parser::StartLinearizedParse( } if (bLoadV4) { - m_pTrailer = LoadTrailerV4(); - if (!m_pTrailer) + std::unique_ptr trailer = LoadTrailerV4(); + if (!trailer) return SUCCESS; - int32_t xrefsize = GetDirectInteger(m_pTrailer.get(), "Size"); + m_Trailers.push_back(std::move(trailer)); + m_TrailerPos = m_Trailers.size() - 1; + int32_t xrefsize = GetDirectInteger(GetTrailer(), "Size"); if (xrefsize > 0) ShrinkObjectMap(xrefsize); } @@ -1559,8 +1566,6 @@ bool CPDF_Parser::LoadLinearizedAllCrossRefV5(FX_FILESIZE xrefpos) { CPDF_Parser::Error CPDF_Parser::LoadLinearizedMainXRefTable() { uint32_t dwSaveMetadataObjnum = m_pSyntax->m_MetadataObjnum; m_pSyntax->m_MetadataObjnum = 0; - if (m_pTrailer) - m_Trailers.push_back(std::move(m_pTrailer)); m_pSyntax->SetPos(m_LastXRefOffset - m_pSyntax->m_HeaderOffset); uint8_t ch = 0; diff --git a/core/fpdfapi/parser/cpdf_parser.h b/core/fpdfapi/parser/cpdf_parser.h index 8f55ddb325..efe10555f7 100644 --- a/core/fpdfapi/parser/cpdf_parser.h +++ b/core/fpdfapi/parser/cpdf_parser.h @@ -7,6 +7,7 @@ #ifndef CORE_FPDFAPI_PARSER_CPDF_PARSER_H_ #define CORE_FPDFAPI_PARSER_CPDF_PARSER_H_ +#include #include #include #include @@ -41,6 +42,8 @@ class CPDF_Parser { // are higher, but this may be large enough in practice. static const uint32_t kMaxObjectNumber = 1048576; + static const size_t kInvalidPos = std::numeric_limits::max(); + CPDF_Parser(); ~CPDF_Parser(); @@ -51,7 +54,10 @@ class CPDF_Parser { void SetPassword(const char* password) { m_Password = password; } CFX_ByteString GetPassword() { return m_Password; } - CPDF_Dictionary* GetTrailer() const { return m_pTrailer.get(); } + CPDF_Dictionary* GetTrailer() const { + return m_TrailerPos == kInvalidPos ? nullptr + : m_Trailers[m_TrailerPos].get(); + } FX_FILESIZE GetLastXRefOffset() const { return m_LastXRefOffset; } uint32_t GetPermissions() const; @@ -161,8 +167,8 @@ class CPDF_Parser { std::unique_ptr m_pSecurityHandler; CFX_ByteString m_Password; std::set m_SortedOffset; - std::unique_ptr m_pTrailer; std::vector> m_Trailers; + size_t m_TrailerPos; std::unique_ptr m_pLinearized; uint32_t m_dwXrefStartObjNum; -- cgit v1.2.3