Check for repeated pages in CPDF_DataAvail::GetPageKids().
Page objects can form cycles. Detect and avoid them.
Bug: chromium:1201087
Change-Id: I00c7374f406de8e561a81f037f55101042695f21
Reviewed-on: https://pdfium-review.googlesource.com/c/pdfium/+/80150
Reviewed-by: Tom Sepez <tsepez@chromium.org>
Commit-Queue: Lei Zhang <thestig@chromium.org>
diff --git a/core/fpdfapi/parser/cpdf_data_avail.cpp b/core/fpdfapi/parser/cpdf_data_avail.cpp
index 8f59630..e743483 100644
--- a/core/fpdfapi/parser/cpdf_data_avail.cpp
+++ b/core/fpdfapi/parser/cpdf_data_avail.cpp
@@ -24,6 +24,7 @@
#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/check.h"
@@ -104,6 +105,8 @@
if (!m_dwFileLen)
return DataError;
+ 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())
@@ -346,15 +349,17 @@
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) {
+ CPDF_Reference* pRef = ToReference(pArrayObj.Get());
+ if (pRef)
+ object_numbers.push_back(pRef->GetRefObjNum());
}
break;
}
@@ -362,6 +367,12 @@
m_docStatus = PDF_DATAAVAIL_ERROR;
return false;
}
+
+ for (uint32_t num : object_numbers) {
+ bool inserted = m_SeenPageObjList.insert(num).second;
+ if (inserted)
+ m_PageObjList.push_back(num);
+ }
return true;
}
diff --git a/core/fpdfapi/parser/cpdf_data_avail.h b/core/fpdfapi/parser/cpdf_data_avail.h
index bbeb987..8dc0394 100644
--- a/core/fpdfapi/parser/cpdf_data_avail.h
+++ b/core/fpdfapi/parser/cpdf_data_avail.h
@@ -178,6 +178,7 @@
const FX_FILESIZE m_dwFileLen;
UnownedPtr<CPDF_Document> m_pDocument;
std::vector<uint32_t> m_PageObjList;
+ std::set<uint32_t> m_SeenPageObjList;
uint32_t m_PagesObjNum = 0;
bool m_bLinearedDataOK = false;
bool m_bMainXRefLoadTried = false;