diff options
Diffstat (limited to 'core/fpdfapi/parser/cpdf_data_avail.cpp')
-rw-r--r-- | core/fpdfapi/parser/cpdf_data_avail.cpp | 561 |
1 files changed, 290 insertions, 271 deletions
diff --git a/core/fpdfapi/parser/cpdf_data_avail.cpp b/core/fpdfapi/parser/cpdf_data_avail.cpp index 457ae61c4..7db348a8d 100644 --- a/core/fpdfapi/parser/cpdf_data_avail.cpp +++ b/core/fpdfapi/parser/cpdf_data_avail.cpp @@ -1,4 +1,4 @@ -// Copyright 2016 PDFium Authors. All rights reserved. +// Copyright 2016 The PDFium Authors // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. @@ -24,32 +24,31 @@ #include "core/fpdfapi/parser/cpdf_stream.h" #include "core/fpdfapi/parser/cpdf_syntax_parser.h" #include "core/fpdfapi/parser/fpdf_parser_utility.h" +#include "core/fxcrt/autorestorer.h" #include "core/fxcrt/fx_extension.h" #include "core/fxcrt/fx_safe_types.h" -#include "third_party/base/compiler_specific.h" +#include "core/fxcrt/stl_util.h" +#include "third_party/base/check.h" +#include "third_party/base/containers/contains.h" +#include "third_party/base/notreached.h" #include "third_party/base/numerics/safe_conversions.h" -#include "third_party/base/ptr_util.h" -#include "third_party/base/stl_util.h" namespace { -// static -CPDF_Object* GetResourceObject(CPDF_Dictionary* pDict) { +RetainPtr<CPDF_Object> GetResourceObject(RetainPtr<CPDF_Dictionary> pDict) { constexpr size_t kMaxHierarchyDepth = 64; size_t depth = 0; - CPDF_Dictionary* dictionary_to_check = pDict; - while (dictionary_to_check) { - CPDF_Object* result = dictionary_to_check->GetObjectFor("Resources"); + while (pDict) { + RetainPtr<CPDF_Object> result = pDict->GetMutableObjectFor("Resources"); if (result) return result; - CPDF_Object* parent = dictionary_to_check->GetObjectFor("Parent"); - dictionary_to_check = parent ? parent->GetDict() : nullptr; - if (++depth > kMaxHierarchyDepth) { // We have cycle in parents hierarchy. return nullptr; } + RetainPtr<CPDF_Object> parent = pDict->GetMutableObjectFor("Parent"); + pDict = parent ? parent->GetMutableDict() : nullptr; } return nullptr; } @@ -59,7 +58,7 @@ class HintsScope { HintsScope(RetainPtr<CPDF_ReadValidator> validator, CPDF_DataAvail::DownloadHints* hints) : validator_(std::move(validator)) { - ASSERT(validator_); + DCHECK(validator_); validator_->SetDownloadHints(hints); } @@ -71,18 +70,15 @@ class HintsScope { } // namespace -CPDF_DataAvail::FileAvail::~FileAvail() {} +CPDF_DataAvail::FileAvail::~FileAvail() = default; -CPDF_DataAvail::DownloadHints::~DownloadHints() {} +CPDF_DataAvail::DownloadHints::~DownloadHints() = default; -CPDF_DataAvail::CPDF_DataAvail( - FileAvail* pFileAvail, - const RetainPtr<IFX_SeekableReadStream>& pFileRead, - bool bSupportHintTable) - : m_pFileRead( - pdfium::MakeRetain<CPDF_ReadValidator>(pFileRead, pFileAvail)), - m_dwFileLen(m_pFileRead->GetSize()), - m_bSupportHintTable(bSupportHintTable) {} +CPDF_DataAvail::CPDF_DataAvail(FileAvail* pFileAvail, + RetainPtr<IFX_SeekableReadStream> pFileRead) + : m_pFileRead(pdfium::MakeRetain<CPDF_ReadValidator>(std::move(pFileRead), + pFileAvail)), + m_dwFileLen(m_pFileRead->GetSize()) {} CPDF_DataAvail::~CPDF_DataAvail() { m_pHintTables.reset(); @@ -101,47 +97,49 @@ void CPDF_DataAvail::OnObservableDestroyed() { CPDF_DataAvail::DocAvailStatus CPDF_DataAvail::IsDocAvail( DownloadHints* pHints) { if (!m_dwFileLen) - return DataError; + return kDataError; + DCHECK(m_SeenPageObjList.empty()); + AutoRestorer<std::set<uint32_t>> seen_objects_restorer(&m_SeenPageObjList); const HintsScope hints_scope(GetValidator(), pHints); while (!m_bDocAvail) { if (!CheckDocStatus()) - return DataNotAvailable; + return kDataNotAvailable; } - return DataAvailable; + return kDataAvailable; } bool CPDF_DataAvail::CheckDocStatus() { - switch (m_docStatus) { - case PDF_DATAAVAIL_HEADER: + switch (m_internalStatus) { + case InternalStatus::kHeader: return CheckHeader(); - case PDF_DATAAVAIL_FIRSTPAGE: + case InternalStatus::kFirstPage: return CheckFirstPage(); - case PDF_DATAAVAIL_HINTTABLE: + case InternalStatus::kHintTable: return CheckHintTables(); - case PDF_DATAAVAIL_LOADALLCROSSREF: + case InternalStatus::kLoadAllCrossRef: return CheckAndLoadAllXref(); - case PDF_DATAAVAIL_LOADALLFILE: + case InternalStatus::kLoadAllFile: return LoadAllFile(); - case PDF_DATAAVAIL_ROOT: + case InternalStatus::kRoot: return CheckRoot(); - case PDF_DATAAVAIL_INFO: + case InternalStatus::kInfo: return CheckInfo(); - case PDF_DATAAVAIL_PAGETREE: + case InternalStatus::kPageTree: if (m_bTotalLoadPageTree) return CheckPages(); return LoadDocPages(); - case PDF_DATAAVAIL_PAGE: + case InternalStatus::kPage: if (m_bTotalLoadPageTree) return CheckPage(); - m_docStatus = PDF_DATAAVAIL_PAGE_LATERLOAD; + m_internalStatus = InternalStatus::kPageLaterLoad; return true; - case PDF_DATAAVAIL_ERROR: + case InternalStatus::kError: return LoadAllFile(); - case PDF_DATAAVAIL_PAGE_LATERLOAD: - m_docStatus = PDF_DATAAVAIL_PAGE; - FALLTHROUGH; + case InternalStatus::kPageLaterLoad: + m_internalStatus = InternalStatus::kPage; + [[fallthrough]]; default: m_bDocAvail = true; return true; @@ -149,12 +147,12 @@ bool CPDF_DataAvail::CheckDocStatus() { } bool CPDF_DataAvail::CheckPageStatus() { - switch (m_docStatus) { - case PDF_DATAAVAIL_PAGETREE: + switch (m_internalStatus) { + case InternalStatus::kPageTree: return CheckPages(); - case PDF_DATAAVAIL_PAGE: + case InternalStatus::kPage: return CheckPage(); - case PDF_DATAAVAIL_ERROR: + case InternalStatus::kError: return LoadAllFile(); default: m_bPagesTreeLoad = true; @@ -165,7 +163,7 @@ bool CPDF_DataAvail::CheckPageStatus() { bool CPDF_DataAvail::LoadAllFile() { if (GetValidator()->CheckWholeFileAndRequestIfUnavailable()) { - m_docStatus = PDF_DATAAVAIL_DONE; + m_internalStatus = InternalStatus::kDone; return true; } return false; @@ -173,27 +171,27 @@ bool CPDF_DataAvail::LoadAllFile() { bool CPDF_DataAvail::CheckAndLoadAllXref() { if (!m_pCrossRefAvail) { - const CPDF_ReadValidator::Session read_session(GetValidator()); + CPDF_ReadValidator::ScopedSession read_session(GetValidator()); const FX_FILESIZE last_xref_offset = m_parser.ParseStartXRef(); if (GetValidator()->has_read_problems()) return false; if (last_xref_offset <= 0) { - m_docStatus = PDF_DATAAVAIL_ERROR; + m_internalStatus = InternalStatus::kError; return false; } - m_pCrossRefAvail = pdfium::MakeUnique<CPDF_CrossRefAvail>(GetSyntaxParser(), - last_xref_offset); + m_pCrossRefAvail = std::make_unique<CPDF_CrossRefAvail>(GetSyntaxParser(), + last_xref_offset); } switch (m_pCrossRefAvail->CheckAvail()) { - case DocAvailStatus::DataAvailable: + case kDataAvailable: break; - case DocAvailStatus::DataNotAvailable: + case kDataNotAvailable: return false; - case DocAvailStatus::DataError: - m_docStatus = PDF_DATAAVAIL_ERROR; + case kDataError: + m_internalStatus = InternalStatus::kError; return false; default: NOTREACHED(); @@ -202,33 +200,29 @@ bool CPDF_DataAvail::CheckAndLoadAllXref() { if (!m_parser.LoadAllCrossRefV4(m_pCrossRefAvail->last_crossref_offset()) && !m_parser.LoadAllCrossRefV5(m_pCrossRefAvail->last_crossref_offset())) { - m_docStatus = PDF_DATAAVAIL_LOADALLFILE; + m_internalStatus = InternalStatus::kLoadAllFile; return false; } - m_docStatus = PDF_DATAAVAIL_ROOT; + m_internalStatus = InternalStatus::kRoot; return true; } RetainPtr<CPDF_Object> CPDF_DataAvail::GetObject(uint32_t objnum, bool* pExistInFile) { - CPDF_Parser* pParser = nullptr; - - if (pExistInFile) - *pExistInFile = true; - - pParser = m_pDocument ? m_pDocument->GetParser() : &m_parser; + *pExistInFile = false; + CPDF_Parser* pParser = m_pDocument ? m_pDocument->GetParser() : &m_parser; + if (!pParser) + return nullptr; - RetainPtr<CPDF_Object> pRet; - if (pParser) { - const CPDF_ReadValidator::Session read_session(GetValidator()); - pRet = pParser->ParseIndirectObject(objnum); - if (GetValidator()->has_read_problems()) - return nullptr; - } + CPDF_ReadValidator::ScopedSession read_session(GetValidator()); + RetainPtr<CPDF_Object> pRet = pParser->ParseIndirectObject(objnum); + if (!pRet) + return nullptr; - if (!pRet && pExistInFile) - *pExistInFile = false; + *pExistInFile = true; + if (GetValidator()->has_read_problems()) + return nullptr; return pRet; } @@ -236,54 +230,64 @@ RetainPtr<CPDF_Object> CPDF_DataAvail::GetObject(uint32_t objnum, bool CPDF_DataAvail::CheckInfo() { const uint32_t dwInfoObjNum = m_parser.GetInfoObjNum(); if (dwInfoObjNum == CPDF_Object::kInvalidObjNum) { - m_docStatus = PDF_DATAAVAIL_PAGETREE; + m_internalStatus = InternalStatus::kPageTree; return true; } - const CPDF_ReadValidator::Session read_session(GetValidator()); + CPDF_ReadValidator::ScopedSession read_session(GetValidator()); m_parser.ParseIndirectObject(dwInfoObjNum); if (GetValidator()->has_read_problems()) return false; - m_docStatus = PDF_DATAAVAIL_PAGETREE; + m_internalStatus = InternalStatus::kPageTree; return true; } bool CPDF_DataAvail::CheckRoot() { const uint32_t dwRootObjNum = m_parser.GetRootObjNum(); if (dwRootObjNum == CPDF_Object::kInvalidObjNum) { - m_docStatus = PDF_DATAAVAIL_ERROR; + m_internalStatus = InternalStatus::kError; return true; } - const CPDF_ReadValidator::Session read_session(GetValidator()); + CPDF_ReadValidator::ScopedSession read_session(GetValidator()); m_pRoot = ToDictionary(m_parser.ParseIndirectObject(dwRootObjNum)); if (GetValidator()->has_read_problems()) return false; - const CPDF_Reference* pRef = - ToReference(m_pRoot ? m_pRoot->GetObjectFor("Pages") : nullptr); + if (!m_pRoot) { + m_internalStatus = InternalStatus::kError; + return false; + } + + RetainPtr<const CPDF_Reference> pRef = + ToReference(m_pRoot->GetObjectFor("Pages")); if (!pRef) { - m_docStatus = PDF_DATAAVAIL_ERROR; + m_internalStatus = InternalStatus::kError; return false; } m_PagesObjNum = pRef->GetRefObjNum(); - m_docStatus = PDF_DATAAVAIL_INFO; + m_internalStatus = InternalStatus::kInfo; return true; } bool CPDF_DataAvail::PreparePageItem() { const CPDF_Dictionary* pRoot = m_pDocument->GetRoot(); - const CPDF_Reference* pRef = - ToReference(pRoot ? pRoot->GetObjectFor("Pages") : nullptr); + if (!pRoot) { + m_internalStatus = InternalStatus::kError; + return false; + } + + RetainPtr<const CPDF_Reference> pRef = + ToReference(pRoot->GetObjectFor("Pages")); if (!pRef) { - m_docStatus = PDF_DATAAVAIL_ERROR; + m_internalStatus = InternalStatus::kError; return false; } m_PagesObjNum = pRef->GetRefObjNum(); - m_docStatus = PDF_DATAAVAIL_PAGETREE; + m_internalStatus = InternalStatus::kPageTree; return true; } @@ -305,21 +309,23 @@ bool CPDF_DataAvail::CheckPage() { UnavailObjList.push_back(dwPageObjNum); continue; } - CPDF_Array* pArray = ToArray(pObj.Get()); - if (pArray) { - CPDF_ArrayLocker locker(pArray); - for (const auto& pArrayObj : locker) { - if (CPDF_Reference* pRef = ToReference(pArrayObj.Get())) - UnavailObjList.push_back(pRef->GetRefObjNum()); - } - } - if (!pObj->IsDictionary()) - continue; - ByteString type = pObj->GetDict()->GetStringFor("Type"); - if (type == "Pages") { - m_PagesArray.push_back(std::move(pObj)); - continue; + switch (pObj->GetType()) { + case CPDF_Object::kArray: { + CPDF_ArrayLocker locker(pObj->AsArray()); + for (const auto& pArrayObj : locker) { + const CPDF_Reference* pRef = ToReference(pArrayObj.Get()); + if (pRef) + UnavailObjList.push_back(pRef->GetRefObjNum()); + } + break; + } + case CPDF_Object::kDictionary: + if (pObj->GetDict()->GetNameFor("Type") == "Pages") + m_PagesArray.push_back(std::move(pObj)); + break; + default: + break; } } m_PageObjList.clear(); @@ -332,39 +338,50 @@ bool CPDF_DataAvail::CheckPage() { RetainPtr<CPDF_Object> pPages = std::move(m_PagesArray[i]); if (pPages && !GetPageKids(pPages.Get())) { m_PagesArray.clear(); - m_docStatus = PDF_DATAAVAIL_ERROR; + m_internalStatus = InternalStatus::kError; return false; } } m_PagesArray.clear(); if (m_PageObjList.empty()) - m_docStatus = PDF_DATAAVAIL_DONE; + m_internalStatus = InternalStatus::kDone; return true; } bool CPDF_DataAvail::GetPageKids(CPDF_Object* pPages) { - CPDF_Dictionary* pDict = pPages->GetDict(); - CPDF_Object* pKids = pDict ? pDict->GetObjectFor("Kids") : nullptr; + RetainPtr<const CPDF_Dictionary> pDict = pPages->GetDict(); + if (!pDict) + return true; + + RetainPtr<const CPDF_Object> pKids = pDict->GetObjectFor("Kids"); if (!pKids) return true; + std::vector<uint32_t> object_numbers; switch (pKids->GetType()) { case CPDF_Object::kReference: - m_PageObjList.push_back(pKids->AsReference()->GetRefObjNum()); + object_numbers.push_back(pKids->AsReference()->GetRefObjNum()); break; case CPDF_Object::kArray: { - CPDF_Array* pKidsArray = pKids->AsArray(); - for (size_t i = 0; i < pKidsArray->size(); ++i) { - if (CPDF_Reference* pRef = ToReference(pKidsArray->GetObjectAt(i))) - m_PageObjList.push_back(pRef->GetRefObjNum()); + CPDF_ArrayLocker locker(pKids->AsArray()); + for (const auto& pArrayObj : locker) { + const CPDF_Reference* pRef = ToReference(pArrayObj.Get()); + if (pRef) + object_numbers.push_back(pRef->GetRefObjNum()); } break; } default: - m_docStatus = PDF_DATAAVAIL_ERROR; + m_internalStatus = InternalStatus::kError; return false; } + + for (uint32_t num : object_numbers) { + bool inserted = m_SeenPageObjList.insert(num).second; + if (inserted) + m_PageObjList.push_back(num); + } return true; } @@ -372,37 +389,37 @@ bool CPDF_DataAvail::CheckPages() { bool bExists = false; RetainPtr<CPDF_Object> pPages = GetObject(m_PagesObjNum, &bExists); if (!bExists) { - m_docStatus = PDF_DATAAVAIL_LOADALLFILE; + m_internalStatus = InternalStatus::kLoadAllFile; return true; } if (!pPages) { - if (m_docStatus == PDF_DATAAVAIL_ERROR) { - m_docStatus = PDF_DATAAVAIL_LOADALLFILE; + if (m_internalStatus == InternalStatus::kError) { + m_internalStatus = InternalStatus::kLoadAllFile; return true; } return false; } if (!GetPageKids(pPages.Get())) { - m_docStatus = PDF_DATAAVAIL_ERROR; + m_internalStatus = InternalStatus::kError; return false; } - m_docStatus = PDF_DATAAVAIL_PAGE; + m_internalStatus = InternalStatus::kPage; return true; } bool CPDF_DataAvail::CheckHeader() { switch (CheckHeaderAndLinearized()) { - case DocAvailStatus::DataAvailable: - m_docStatus = m_pLinearized ? PDF_DATAAVAIL_FIRSTPAGE - : PDF_DATAAVAIL_LOADALLCROSSREF; + case kDataAvailable: + m_internalStatus = m_pLinearized ? InternalStatus::kFirstPage + : InternalStatus::kLoadAllCrossRef; return true; - case DocAvailStatus::DataNotAvailable: + case kDataNotAvailable: return false; - case DocAvailStatus::DataError: - m_docStatus = PDF_DATAAVAIL_ERROR; + case kDataError: + m_internalStatus = InternalStatus::kError; return true; default: NOTREACHED(); @@ -414,7 +431,7 @@ bool CPDF_DataAvail::CheckFirstPage() { if (!m_pLinearized->GetFirstPageEndOffset() || !m_pLinearized->GetFileSize() || !m_pLinearized->GetMainXRefTableFirstEntryOffset()) { - m_docStatus = PDF_DATAAVAIL_ERROR; + m_internalStatus = InternalStatus::kError; return false; } @@ -429,24 +446,23 @@ bool CPDF_DataAvail::CheckFirstPage() { data_size)) return false; - m_docStatus = - m_bSupportHintTable ? PDF_DATAAVAIL_HINTTABLE : PDF_DATAAVAIL_DONE; + m_internalStatus = InternalStatus::kHintTable; return true; } bool CPDF_DataAvail::CheckHintTables() { - const CPDF_ReadValidator::Session read_session(GetValidator()); + CPDF_ReadValidator::ScopedSession read_session(GetValidator()); m_pHintTables = CPDF_HintTables::Parse(GetSyntaxParser(), m_pLinearized.get()); if (GetValidator()->read_error()) { - m_docStatus = PDF_DATAAVAIL_ERROR; + m_internalStatus = InternalStatus::kError; return true; } if (GetValidator()->has_unavailable_data()) return false; - m_docStatus = PDF_DATAAVAIL_DONE; + m_internalStatus = InternalStatus::kDone; return true; } @@ -466,59 +482,59 @@ RetainPtr<CPDF_Object> CPDF_DataAvail::ParseIndirectObjectAt( CPDF_DataAvail::DocLinearizationStatus CPDF_DataAvail::IsLinearizedPDF() { switch (CheckHeaderAndLinearized()) { - case DocAvailStatus::DataAvailable: - return m_pLinearized ? DocLinearizationStatus::Linearized - : DocLinearizationStatus::NotLinearized; - case DocAvailStatus::DataNotAvailable: - return DocLinearizationStatus::LinearizationUnknown; - case DocAvailStatus::DataError: - return DocLinearizationStatus::NotLinearized; + case kDataAvailable: + return m_pLinearized ? kLinearized : kNotLinearized; + case kDataNotAvailable: + return kLinearizationUnknown; + case kDataError: + return kNotLinearized; default: NOTREACHED(); - return DocLinearizationStatus::LinearizationUnknown; + return kLinearizationUnknown; } } CPDF_DataAvail::DocAvailStatus CPDF_DataAvail::CheckHeaderAndLinearized() { if (m_bHeaderAvail) - return DocAvailStatus::DataAvailable; + return kDataAvailable; - const CPDF_ReadValidator::Session read_session(GetValidator()); - const Optional<FX_FILESIZE> header_offset = GetHeaderOffset(GetValidator()); + CPDF_ReadValidator::ScopedSession read_session(GetValidator()); + const absl::optional<FX_FILESIZE> header_offset = + GetHeaderOffset(GetValidator()); if (GetValidator()->has_read_problems()) - return DocAvailStatus::DataNotAvailable; + return kDataNotAvailable; - if (!header_offset) - return DocAvailStatus::DataError; + if (!header_offset.has_value()) + return kDataError; - m_parser.m_pSyntax = - pdfium::MakeUnique<CPDF_SyntaxParser>(GetValidator(), *header_offset); + m_parser.m_pSyntax = std::make_unique<CPDF_SyntaxParser>( + GetValidator(), header_offset.value()); m_pLinearized = m_parser.ParseLinearizedHeader(); if (GetValidator()->has_read_problems()) - return DocAvailStatus::DataNotAvailable; + return kDataNotAvailable; m_bHeaderAvail = true; - return DocAvailStatus::DataAvailable; + return kDataAvailable; } bool CPDF_DataAvail::CheckPage(uint32_t dwPage) { while (true) { - switch (m_docStatus) { - case PDF_DATAAVAIL_PAGETREE: + switch (m_internalStatus) { + case InternalStatus::kPageTree: if (!LoadDocPages()) return false; break; - case PDF_DATAAVAIL_PAGE: + case InternalStatus::kPage: if (!LoadDocPage(dwPage)) return false; break; - case PDF_DATAAVAIL_ERROR: + case InternalStatus::kError: return LoadAllFile(); default: m_bPagesTreeLoad = true; m_bPagesLoad = true; m_bCurPageDictLoadOK = true; - m_docStatus = PDF_DATAAVAIL_PAGE; + m_internalStatus = InternalStatus::kPage; return true; } } @@ -529,26 +545,26 @@ bool CPDF_DataAvail::CheckArrayPageNode(uint32_t dwPageNo, bool bExists = false; RetainPtr<CPDF_Object> pPages = GetObject(dwPageNo, &bExists); if (!bExists) { - m_docStatus = PDF_DATAAVAIL_ERROR; + m_internalStatus = InternalStatus::kError; return false; } if (!pPages) return false; - CPDF_Array* pArray = pPages->AsArray(); + const CPDF_Array* pArray = pPages->AsArray(); if (!pArray) { - m_docStatus = PDF_DATAAVAIL_ERROR; + m_internalStatus = InternalStatus::kError; return false; } - pPageNode->m_type = PDF_PAGENODE_PAGES; + pPageNode->m_type = PageNode::Type::kPages; for (size_t i = 0; i < pArray->size(); ++i) { - CPDF_Reference* pKid = ToReference(pArray->GetObjectAt(i)); + RetainPtr<const CPDF_Reference> pKid = ToReference(pArray->GetObjectAt(i)); if (!pKid) continue; - auto pNode = pdfium::MakeUnique<PageNode>(); + auto pNode = std::make_unique<PageNode>(); pNode->m_dwPageNo = pKid->GetRefObjNum(); pPageNode->m_ChildNodes.push_back(std::move(pNode)); } @@ -560,7 +576,7 @@ bool CPDF_DataAvail::CheckUnknownPageNode(uint32_t dwPageNo, bool bExists = false; RetainPtr<CPDF_Object> pPage = GetObject(dwPageNo, &bExists); if (!bExists) { - m_docStatus = PDF_DATAAVAIL_ERROR; + m_internalStatus = InternalStatus::kError; return false; } @@ -569,51 +585,52 @@ bool CPDF_DataAvail::CheckUnknownPageNode(uint32_t dwPageNo, if (pPage->IsArray()) { pPageNode->m_dwPageNo = dwPageNo; - pPageNode->m_type = PDF_PAGENODE_ARRAY; + pPageNode->m_type = PageNode::Type::kArray; return true; } if (!pPage->IsDictionary()) { - m_docStatus = PDF_DATAAVAIL_ERROR; + m_internalStatus = InternalStatus::kError; return false; } pPageNode->m_dwPageNo = dwPageNo; - CPDF_Dictionary* pDict = pPage->GetDict(); - const ByteString type = pDict->GetStringFor("Type"); + RetainPtr<CPDF_Dictionary> pDict = pPage->GetMutableDict(); + const ByteString type = pDict->GetNameFor("Type"); if (type == "Page") { - pPageNode->m_type = PDF_PAGENODE_PAGE; + pPageNode->m_type = PageNode::Type::kPage; return true; } if (type != "Pages") { - m_docStatus = PDF_DATAAVAIL_ERROR; + m_internalStatus = InternalStatus::kError; return false; } - pPageNode->m_type = PDF_PAGENODE_PAGES; - CPDF_Object* pKids = pDict->GetObjectFor("Kids"); + pPageNode->m_type = PageNode::Type::kPages; + RetainPtr<CPDF_Object> pKids = pDict->GetMutableObjectFor("Kids"); if (!pKids) { - m_docStatus = PDF_DATAAVAIL_PAGE; + m_internalStatus = InternalStatus::kPage; return true; } switch (pKids->GetType()) { case CPDF_Object::kReference: { - CPDF_Reference* pKid = pKids->AsReference(); - auto pNode = pdfium::MakeUnique<PageNode>(); + const CPDF_Reference* pKid = pKids->AsReference(); + auto pNode = std::make_unique<PageNode>(); pNode->m_dwPageNo = pKid->GetRefObjNum(); pPageNode->m_ChildNodes.push_back(std::move(pNode)); break; } case CPDF_Object::kArray: { - CPDF_Array* pKidsArray = pKids->AsArray(); + const CPDF_Array* pKidsArray = pKids->AsArray(); for (size_t i = 0; i < pKidsArray->size(); ++i) { - CPDF_Reference* pKid = ToReference(pKidsArray->GetObjectAt(i)); + RetainPtr<const CPDF_Reference> pKid = + ToReference(pKidsArray->GetObjectAt(i)); if (!pKid) continue; - auto pNode = pdfium::MakeUnique<PageNode>(); + auto pNode = std::make_unique<PageNode>(); pNode->m_dwPageNo = pKid->GetRefObjNum(); pPageNode->m_ChildNodes.push_back(std::move(pNode)); } @@ -632,9 +649,9 @@ bool CPDF_DataAvail::CheckPageNode(const CPDF_DataAvail::PageNode& pageNode, if (level >= kMaxPageRecursionDepth) return false; - int32_t iSize = pdfium::CollectionSize<int32_t>(pageNode.m_ChildNodes); + int32_t iSize = fxcrt::CollectionSize<int32_t>(pageNode.m_ChildNodes); if (iSize <= 0 || iPage >= iSize) { - m_docStatus = PDF_DATAAVAIL_ERROR; + m_internalStatus = InternalStatus::kError; return false; } for (int32_t i = 0; i < iSize; ++i) { @@ -642,33 +659,33 @@ bool CPDF_DataAvail::CheckPageNode(const CPDF_DataAvail::PageNode& pageNode, if (!pNode) continue; - if (pNode->m_type == PDF_PAGENODE_UNKNOWN) { + if (pNode->m_type == PageNode::Type::kUnknown) { // Updates the type for the unknown page node. if (!CheckUnknownPageNode(pNode->m_dwPageNo, pNode)) return false; } - if (pNode->m_type == PDF_PAGENODE_ARRAY) { + if (pNode->m_type == PageNode::Type::kArray) { // Updates a more specific type for the array page node. if (!CheckArrayPageNode(pNode->m_dwPageNo, pNode)) return false; } switch (pNode->m_type) { - case PDF_PAGENODE_PAGE: + case PageNode::Type::kPage: iCount++; if (iPage == iCount && m_pDocument) m_pDocument->SetPageObjNum(iPage, pNode->m_dwPageNo); break; - case PDF_PAGENODE_PAGES: + case PageNode::Type::kPages: if (!CheckPageNode(*pNode, iPage, iCount, level + 1)) return false; break; - case PDF_PAGENODE_UNKNOWN: - case PDF_PAGENODE_ARRAY: + case PageNode::Type::kUnknown: + case PageNode::Type::kArray: // Already converted above, error if we get here. return false; } if (iPage == iCount) { - m_docStatus = PDF_DATAAVAIL_DONE; + m_internalStatus = InternalStatus::kDone; return true; } } @@ -676,15 +693,15 @@ bool CPDF_DataAvail::CheckPageNode(const CPDF_DataAvail::PageNode& pageNode, } bool CPDF_DataAvail::LoadDocPage(uint32_t dwPage) { - FX_SAFE_INT32 safePage = pdfium::base::checked_cast<int32_t>(dwPage); - int32_t iPage = safePage.ValueOrDie(); + int iPage = pdfium::base::checked_cast<int>(dwPage); if (m_pDocument->GetPageCount() <= iPage || m_pDocument->IsPageLoaded(iPage)) { - m_docStatus = PDF_DATAAVAIL_DONE; + m_internalStatus = InternalStatus::kDone; return true; } - if (m_PageNode.m_type == PDF_PAGENODE_PAGE) { - m_docStatus = iPage == 0 ? PDF_DATAAVAIL_DONE : PDF_DATAAVAIL_ERROR; + if (m_PageNode.m_type == PageNode::Type::kPage) { + m_internalStatus = + iPage == 0 ? InternalStatus::kDone : InternalStatus::kError; return true; } int32_t iCount = -1; @@ -695,15 +712,15 @@ bool CPDF_DataAvail::CheckPageCount() { bool bExists = false; RetainPtr<CPDF_Object> pPages = GetObject(m_PagesObjNum, &bExists); if (!bExists) { - m_docStatus = PDF_DATAAVAIL_ERROR; + m_internalStatus = InternalStatus::kError; return false; } if (!pPages) return false; - CPDF_Dictionary* pPagesDict = pPages->GetDict(); + RetainPtr<const CPDF_Dictionary> pPagesDict = pPages->GetDict(); if (!pPagesDict) { - m_docStatus = PDF_DATAAVAIL_ERROR; + m_internalStatus = InternalStatus::kError; return false; } if (!pPagesDict->KeyExist("Kids")) @@ -717,7 +734,7 @@ bool CPDF_DataAvail::LoadDocPages() { return false; if (CheckPageCount()) { - m_docStatus = PDF_DATAAVAIL_PAGE; + m_internalStatus = InternalStatus::kPage; return true; } @@ -740,11 +757,11 @@ bool CPDF_DataAvail::LoadPages() { CPDF_DataAvail::DocAvailStatus CPDF_DataAvail::CheckLinearizedData() { if (m_bLinearedDataOK) - return DataAvailable; - ASSERT(m_pLinearized); + return kDataAvailable; + DCHECK(m_pLinearized); if (!m_pLinearized->GetMainXRefTableFirstEntryOffset() || !m_pDocument || !m_pDocument->GetParser() || !m_pDocument->GetParser()->GetTrailer()) { - return DataError; + return kDataError; } if (!m_bMainXRefLoadTried) { @@ -752,68 +769,66 @@ CPDF_DataAvail::DocAvailStatus CPDF_DataAvail::CheckLinearizedData() { m_pDocument->GetParser()->GetTrailer()->GetIntegerFor("Prev"); const FX_FILESIZE main_xref_offset = prev.ValueOrDefault(-1); if (main_xref_offset < 0) - return DataError; + return kDataError; if (main_xref_offset == 0) - return DataAvailable; + return kDataAvailable; FX_SAFE_SIZE_T data_size = m_dwFileLen; data_size -= main_xref_offset; if (!data_size.IsValid()) - return DataError; + return kDataError; if (!GetValidator()->CheckDataRangeAndRequestIfUnavailable( main_xref_offset, data_size.ValueOrDie())) - return DataNotAvailable; + return kDataNotAvailable; CPDF_Parser::Error eRet = m_pDocument->GetParser()->LoadLinearizedMainXRefTable(); m_bMainXRefLoadTried = true; if (eRet != CPDF_Parser::SUCCESS) - return DataError; + return kDataError; if (!PreparePageItem()) - return DataNotAvailable; + return kDataNotAvailable; m_bMainXRefLoadedOK = true; m_bLinearedDataOK = true; } - return m_bLinearedDataOK ? DataAvailable : DataNotAvailable; + return m_bLinearedDataOK ? kDataAvailable : kDataNotAvailable; } CPDF_DataAvail::DocAvailStatus CPDF_DataAvail::IsPageAvail( uint32_t dwPage, DownloadHints* pHints) { if (!m_pDocument) - return DataError; + return kDataError; - const FX_SAFE_INT32 safePage = pdfium::base::checked_cast<int32_t>(dwPage); - if (!safePage.IsValid()) - return DataError; - - if (safePage.ValueOrDie() >= m_pDocument->GetPageCount()) { + const int iPage = pdfium::base::checked_cast<int>(dwPage); + if (iPage >= m_pDocument->GetPageCount()) { // This is XFA page. - return DataAvailable; + return kDataAvailable; } if (IsFirstCheck(dwPage)) { m_bCurPageDictLoadOK = false; } - if (pdfium::ContainsKey(m_pagesLoadState, dwPage)) - return DataAvailable; + if (pdfium::Contains(m_pagesLoadState, dwPage)) + return kDataAvailable; const HintsScope hints_scope(GetValidator(), pHints); if (m_pLinearized) { if (dwPage == m_pLinearized->GetFirstPageNo()) { - auto* pPageDict = m_pDocument->GetPageDictionary(safePage.ValueOrDie()); + RetainPtr<const CPDF_Dictionary> pPageDict = + m_pDocument->GetPageDictionary(iPage); if (!pPageDict) - return DataError; + return kDataError; - auto page_num_obj = std::make_pair( - dwPage, pdfium::MakeUnique<CPDF_PageObjectAvail>( - GetValidator(), m_pDocument.Get(), pPageDict)); + auto page_num_obj = + std::make_pair(dwPage, std::make_unique<CPDF_PageObjectAvail>( + GetValidator(), m_pDocument, pPageDict)); CPDF_PageObjectAvail* page_obj_avail = m_PagesObjAvail.insert(std::move(page_num_obj)).first->second.get(); @@ -822,83 +837,84 @@ CPDF_DataAvail::DocAvailStatus CPDF_DataAvail::IsPageAvail( } DocAvailStatus nResult = CheckLinearizedData(); - if (nResult != DataAvailable) + if (nResult != kDataAvailable) return nResult; if (m_pHintTables) { nResult = m_pHintTables->CheckPage(dwPage); - if (nResult != DataAvailable) + if (nResult != kDataAvailable) return nResult; if (GetPageDictionary(dwPage)) { m_pagesLoadState.insert(dwPage); - return DataAvailable; + return kDataAvailable; } } if (!m_bMainXRefLoadedOK) { if (!LoadAllFile()) - return DataNotAvailable; + return kDataNotAvailable; m_pDocument->GetParser()->RebuildCrossRef(); ResetFirstCheck(dwPage); - return DataAvailable; + return kDataAvailable; } if (m_bTotalLoadPageTree) { if (!LoadPages()) - return DataNotAvailable; + return kDataNotAvailable; } else { if (!m_bCurPageDictLoadOK && !CheckPage(dwPage)) - return DataNotAvailable; + return kDataNotAvailable; } } else { if (!m_bTotalLoadPageTree && !m_bCurPageDictLoadOK && !CheckPage(dwPage)) { - return DataNotAvailable; + return kDataNotAvailable; } } - if (CheckAcroForm() == DocFormStatus::FormNotAvailable) - return DataNotAvailable; + if (CheckAcroForm() == kFormNotAvailable) + return kDataNotAvailable; - auto* pPageDict = m_pDocument->GetPageDictionary(safePage.ValueOrDie()); + RetainPtr<CPDF_Dictionary> pPageDict = + m_pDocument->GetMutablePageDictionary(iPage); if (!pPageDict) - return DataError; + return kDataError; { - auto page_num_obj = std::make_pair( - dwPage, pdfium::MakeUnique<CPDF_PageObjectAvail>( - GetValidator(), m_pDocument.Get(), pPageDict)); + auto page_num_obj = + std::make_pair(dwPage, std::make_unique<CPDF_PageObjectAvail>( + GetValidator(), m_pDocument, pPageDict)); CPDF_PageObjectAvail* page_obj_avail = m_PagesObjAvail.insert(std::move(page_num_obj)).first->second.get(); const DocAvailStatus status = page_obj_avail->CheckAvail(); - if (status != DocAvailStatus::DataAvailable) + if (status != kDataAvailable) return status; } - const DocAvailStatus resources_status = CheckResources(pPageDict); - if (resources_status != DocAvailStatus::DataAvailable) + const DocAvailStatus resources_status = CheckResources(std::move(pPageDict)); + if (resources_status != kDataAvailable) return resources_status; m_bCurPageDictLoadOK = false; ResetFirstCheck(dwPage); m_pagesLoadState.insert(dwPage); - return DataAvailable; + return kDataAvailable; } CPDF_DataAvail::DocAvailStatus CPDF_DataAvail::CheckResources( - CPDF_Dictionary* page) { - ASSERT(page); - const CPDF_ReadValidator::Session read_session(GetValidator()); - CPDF_Object* resources = GetResourceObject(page); + RetainPtr<CPDF_Dictionary> page) { + DCHECK(page); + CPDF_ReadValidator::ScopedSession read_session(GetValidator()); + RetainPtr<CPDF_Object> resources = GetResourceObject(std::move(page)); if (GetValidator()->has_read_problems()) - return DocAvailStatus::DataNotAvailable; + return kDataNotAvailable; if (!resources) - return DocAvailStatus::DataAvailable; + return kDataAvailable; CPDF_PageObjectAvail* resource_avail = m_PagesResourcesAvail - .insert(std::make_pair( - resources, pdfium::MakeUnique<CPDF_PageObjectAvail>( - GetValidator(), m_pDocument.Get(), resources))) + .insert(std::make_pair(resources, + std::make_unique<CPDF_PageObjectAvail>( + GetValidator(), m_pDocument, resources))) .first->second.get(); return resource_avail->CheckAvail(); } @@ -918,10 +934,11 @@ int CPDF_DataAvail::GetPageCount() const { return m_pDocument ? m_pDocument->GetPageCount() : 0; } -CPDF_Dictionary* CPDF_DataAvail::GetPageDictionary(int index) const { +RetainPtr<const CPDF_Dictionary> CPDF_DataAvail::GetPageDictionary( + int index) const { if (!m_pDocument || index < 0 || index >= GetPageCount()) return nullptr; - CPDF_Dictionary* page = m_pDocument->GetPageDictionary(index); + RetainPtr<const CPDF_Dictionary> page = m_pDocument->GetPageDictionary(index); if (page) return page; if (!m_pLinearized || !m_pHintTables) @@ -941,8 +958,7 @@ CPDF_Dictionary* CPDF_DataAvail::GetPageDictionary(int index) const { // Page object already can be parsed in document. if (!m_pDocument->GetIndirectObject(dwObjNum)) { m_pDocument->ReplaceIndirectObjectIfHigherGeneration( - dwObjNum, - ParseIndirectObjectAt(szPageStartPos, dwObjNum, m_pDocument.Get())); + dwObjNum, ParseIndirectObjectAt(szPageStartPos, dwObjNum, m_pDocument)); } if (!ValidatePage(index)) return nullptr; @@ -957,64 +973,67 @@ CPDF_DataAvail::DocFormStatus CPDF_DataAvail::IsFormAvail( CPDF_DataAvail::DocFormStatus CPDF_DataAvail::CheckAcroForm() { if (!m_pDocument) - return FormAvailable; + return kFormAvailable; if (m_pLinearized) { DocAvailStatus nDocStatus = CheckLinearizedData(); - if (nDocStatus == DataError) - return FormError; - if (nDocStatus == DataNotAvailable) - return FormNotAvailable; + if (nDocStatus == kDataError) + return kFormError; + if (nDocStatus == kDataNotAvailable) + return kFormNotAvailable; } if (!m_pFormAvail) { - CPDF_Dictionary* pRoot = m_pDocument->GetRoot(); + const CPDF_Dictionary* pRoot = m_pDocument->GetRoot(); if (!pRoot) - return FormAvailable; + return kFormAvailable; - CPDF_Object* pAcroForm = pRoot->GetObjectFor("AcroForm"); + RetainPtr<const CPDF_Object> pAcroForm = pRoot->GetObjectFor("AcroForm"); if (!pAcroForm) - return FormNotExist; + return kFormNotExist; - m_pFormAvail = pdfium::MakeUnique<CPDF_PageObjectAvail>( - GetValidator(), m_pDocument.Get(), pAcroForm); + m_pFormAvail = std::make_unique<CPDF_PageObjectAvail>( + GetValidator(), m_pDocument, std::move(pAcroForm)); } switch (m_pFormAvail->CheckAvail()) { - case DocAvailStatus::DataError: - return DocFormStatus::FormError; - case DocAvailStatus::DataNotAvailable: - return DocFormStatus::FormNotAvailable; - case DocAvailStatus::DataAvailable: - return DocFormStatus::FormAvailable; + case kDataError: + return kFormError; + case kDataNotAvailable: + return kFormNotAvailable; + case kDataAvailable: + return kFormAvailable; default: NOTREACHED(); } - return DocFormStatus::FormError; + return kFormError; } bool CPDF_DataAvail::ValidatePage(uint32_t dwPage) const { - FX_SAFE_INT32 safePage = pdfium::base::checked_cast<int32_t>(dwPage); - auto* pPageDict = m_pDocument->GetPageDictionary(safePage.ValueOrDie()); + int iPage = pdfium::base::checked_cast<int>(dwPage); + RetainPtr<const CPDF_Dictionary> pPageDict = + m_pDocument->GetPageDictionary(iPage); if (!pPageDict) return false; - CPDF_PageObjectAvail obj_avail(GetValidator(), m_pDocument.Get(), pPageDict); - return obj_avail.CheckAvail() == DocAvailStatus::DataAvailable; + + CPDF_PageObjectAvail obj_avail(GetValidator(), m_pDocument, + std::move(pPageDict)); + return obj_avail.CheckAvail() == kDataAvailable; } std::pair<CPDF_Parser::Error, std::unique_ptr<CPDF_Document>> CPDF_DataAvail::ParseDocument( std::unique_ptr<CPDF_Document::RenderDataIface> pRenderData, std::unique_ptr<CPDF_Document::PageDataIface> pPageData, - const char* password) { + const ByteString& password) { if (m_pDocument) { // We already returned parsed document. return std::make_pair(CPDF_Parser::HANDLER_ERROR, nullptr); } - auto document = pdfium::MakeUnique<CPDF_Document>(std::move(pRenderData), - std::move(pPageData)); + auto document = std::make_unique<CPDF_Document>(std::move(pRenderData), + std::move(pPageData)); document->AddObserver(this); - CPDF_ReadValidator::Session read_session(GetValidator()); + CPDF_ReadValidator::ScopedSession read_session(GetValidator()); CPDF_Parser::Error error = document->LoadLinearizedDoc(GetValidator(), password); @@ -1031,6 +1050,6 @@ CPDF_DataAvail::ParseDocument( return std::make_pair(CPDF_Parser::SUCCESS, std::move(document)); } -CPDF_DataAvail::PageNode::PageNode() : m_type(PDF_PAGENODE_UNKNOWN) {} +CPDF_DataAvail::PageNode::PageNode() = default; -CPDF_DataAvail::PageNode::~PageNode() {} +CPDF_DataAvail::PageNode::~PageNode() = default; |