Index: core/fpdfapi/parser/cpdf_data_avail.cpp |
diff --git a/core/fpdfapi/parser/cpdf_data_avail.cpp b/core/fpdfapi/parser/cpdf_data_avail.cpp |
index 3fe4b03da62012ae33d8cbf50944708e5572224f..c1d17a98ed9fc67d06d7e9e81a63d7cdf5f5e700 100644 |
--- a/core/fpdfapi/parser/cpdf_data_avail.cpp |
+++ b/core/fpdfapi/parser/cpdf_data_avail.cpp |
@@ -251,7 +251,6 @@ bool CPDF_DataAvail::CheckDocStatus(DownloadHints* pHints) { |
case PDF_DATAAVAIL_HEADER: |
return CheckHeader(pHints); |
case PDF_DATAAVAIL_FIRSTPAGE: |
- case PDF_DATAAVAIL_FIRSTPAGE_PREPARE: |
return CheckFirstPage(pHints); |
case PDF_DATAAVAIL_HINTTABLE: |
return CheckHintTables(pHints); |
@@ -594,7 +593,6 @@ bool CPDF_DataAvail::CheckFirstPage(DownloadHints* pHints) { |
return false; |
} |
- bool bNeedDownLoad = false; |
uint32_t dwEnd = m_pLinearized->GetFirstPageEndOffset(); |
dwEnd += 512; |
if ((FX_FILESIZE)dwEnd > m_dwFileLen) |
@@ -604,28 +602,6 @@ bool CPDF_DataAvail::CheckFirstPage(DownloadHints* pHints) { |
int32_t iSize = dwEnd > 1024 ? dwEnd - 1024 : 0; |
if (!m_pFileAvail->IsDataAvail(iStartPos, iSize)) { |
pHints->AddSegment(iStartPos, iSize); |
- bNeedDownLoad = true; |
- } |
- |
- m_dwLastXRefOffset = m_pLinearized->GetLastXRefOffset(); |
- FX_FILESIZE dwFileLen = m_pLinearized->GetFileSize(); |
- if (!m_pFileAvail->IsDataAvail(m_dwLastXRefOffset, |
- (uint32_t)(dwFileLen - m_dwLastXRefOffset))) { |
- if (m_docStatus == PDF_DATAAVAIL_FIRSTPAGE) { |
- uint32_t dwSize = (uint32_t)(dwFileLen - m_dwLastXRefOffset); |
- FX_FILESIZE offset = m_dwLastXRefOffset; |
- if (dwSize < 512 && dwFileLen > 512) { |
- dwSize = 512; |
- offset = dwFileLen - 512; |
- } |
- pHints->AddSegment(offset, dwSize); |
- } |
- } else { |
- m_docStatus = PDF_DATAAVAIL_FIRSTPAGE_PREPARE; |
- } |
- |
- if (bNeedDownLoad || m_docStatus != PDF_DATAAVAIL_FIRSTPAGE_PREPARE) { |
- m_docStatus = PDF_DATAAVAIL_FIRSTPAGE_PREPARE; |
return false; |
} |
@@ -649,7 +625,8 @@ bool CPDF_DataAvail::IsDataAvail(FX_FILESIZE offset, |
size += 512; |
if (!m_pFileAvail->IsDataAvail(offset, size)) { |
- pHints->AddSegment(offset, size); |
+ if (pHints) |
+ pHints->AddSegment(offset, size); |
return false; |
} |
return true; |
@@ -1372,16 +1349,20 @@ CPDF_DataAvail::DocAvailStatus CPDF_DataAvail::CheckLinearizedData( |
DownloadHints* pHints) { |
if (m_bLinearedDataOK) |
return DataAvailable; |
+ ASSERT(m_pLinearized); |
+ if (!m_pLinearized->GetLastXRefOffset()) |
+ return DataError; |
if (!m_bMainXRefLoadTried) { |
FX_SAFE_UINT32 data_size = m_dwFileLen; |
- data_size -= m_dwLastXRefOffset; |
+ data_size -= m_pLinearized->GetLastXRefOffset(); |
if (!data_size.IsValid()) |
return DataError; |
- if (!m_pFileAvail->IsDataAvail(m_dwLastXRefOffset, |
+ if (!m_pFileAvail->IsDataAvail(m_pLinearized->GetLastXRefOffset(), |
data_size.ValueOrDie())) { |
- pHints->AddSegment(m_dwLastXRefOffset, data_size.ValueOrDie()); |
+ pHints->AddSegment(m_pLinearized->GetLastXRefOffset(), |
+ data_size.ValueOrDie()); |
return DataNotAvailable; |
} |
@@ -1440,11 +1421,10 @@ CPDF_DataAvail::DocAvailStatus CPDF_DataAvail::CheckLinearizedFirstPage( |
return DataNotAvailable; |
m_bAnnotsLoad = true; |
} |
- |
- DocAvailStatus nRet = CheckLinearizedData(pHints); |
- if (nRet == DataAvailable) |
- m_bPageLoadedOK = false; |
- return nRet; |
+ const bool is_page_valid = ValidatePage(dwPage); |
+ (void)is_page_valid; |
+ ASSERT(is_page_valid); |
+ return DataAvailable; |
} |
bool CPDF_DataAvail::HaveResourceAncestor(CPDF_Dictionary* pDict) { |
@@ -1543,6 +1523,7 @@ CPDF_DataAvail::DocAvailStatus CPDF_DataAvail::IsPageAvail( |
m_pPageDict = m_pDocument->GetPage(safePage.ValueOrDie()); |
if (!m_pPageDict) { |
ResetFirstCheck(dwPage); |
+ // This is XFA page. |
return DataAvailable; |
} |
@@ -1587,6 +1568,9 @@ CPDF_DataAvail::DocAvailStatus CPDF_DataAvail::IsPageAvail( |
ResetFirstCheck(dwPage); |
m_pagesLoadState.insert(dwPage); |
+ const bool is_page_valid = ValidatePage(dwPage); |
+ (void)is_page_valid; |
+ ASSERT(is_page_valid); |
return DataAvailable; |
} |
@@ -1650,6 +1634,9 @@ CPDF_Dictionary* CPDF_DataAvail::GetPage(int index) { |
m_pDocument->ReplaceIndirectObjectIfHigherGeneration( |
dwObjNum, ParseIndirectObjectAt(0, dwObjNum, m_pDocument)); |
} |
+ const bool is_page_valid = ValidatePage(index); |
+ (void)is_page_valid; |
+ ASSERT(is_page_valid); |
return m_pDocument->GetPage(index); |
} |
@@ -1657,6 +1644,13 @@ CPDF_DataAvail::DocFormStatus CPDF_DataAvail::IsFormAvail( |
DownloadHints* pHints) { |
if (!m_pDocument) |
return FormAvailable; |
+ if (m_pLinearized) { |
+ DocAvailStatus nDocStatus = CheckLinearizedData(pHints); |
+ if (nDocStatus == DataError) |
+ return FormError; |
+ if (nDocStatus == DataNotAvailable) |
+ return FormNotAvailable; |
+ } |
if (!m_bLinearizedFormParamLoad) { |
CPDF_Dictionary* pRoot = m_pDocument->GetRoot(); |
@@ -1667,14 +1661,7 @@ CPDF_DataAvail::DocFormStatus CPDF_DataAvail::IsFormAvail( |
if (!pAcroForm) |
return FormNotExist; |
- DocAvailStatus nDocStatus = CheckLinearizedData(pHints); |
- if (nDocStatus == DataError) |
- return FormError; |
- if (nDocStatus == DataNotAvailable) |
- return FormNotAvailable; |
- |
- if (m_objs_array.empty()) |
- m_objs_array.push_back(pAcroForm->GetDict()); |
+ m_objs_array.push_back(pAcroForm->GetDict()); |
m_bLinearizedFormParamLoad = true; |
} |
@@ -1685,9 +1672,36 @@ CPDF_DataAvail::DocFormStatus CPDF_DataAvail::IsFormAvail( |
} |
m_objs_array.clear(); |
+ const bool is_form_valid = ValidateForm(); |
+ (void)is_form_valid; |
+ ASSERT(is_form_valid); |
return FormAvailable; |
} |
+bool CPDF_DataAvail::ValidatePage(uint32_t dwPage) { |
+ FX_SAFE_INT32 safePage = pdfium::base::checked_cast<int32_t>(dwPage); |
+ CPDF_Dictionary* pPageDict = m_pDocument->GetPage(safePage.ValueOrDie()); |
+ if (!pPageDict) |
+ return false; |
+ std::vector<CPDF_Object*> obj_array; |
+ obj_array.push_back(pPageDict); |
+ std::vector<CPDF_Object*> dummy; |
+ return AreObjectsAvailable(obj_array, true, nullptr, dummy); |
+} |
+ |
+bool CPDF_DataAvail::ValidateForm() { |
+ CPDF_Dictionary* pRoot = m_pDocument->GetRoot(); |
+ if (!pRoot) |
+ return true; |
+ CPDF_Object* pAcroForm = pRoot->GetObjectFor("AcroForm"); |
+ if (!pAcroForm) |
+ return false; |
+ std::vector<CPDF_Object*> obj_array; |
+ obj_array.push_back(pAcroForm); |
+ std::vector<CPDF_Object*> dummy; |
+ return AreObjectsAvailable(obj_array, true, nullptr, dummy); |
+} |
+ |
CPDF_DataAvail::PageNode::PageNode() : m_type(PDF_PAGENODE_UNKNOWN) {} |
CPDF_DataAvail::PageNode::~PageNode() { |