Index: core/src/fpdfapi/fpdf_parser/fpdf_parser_document.cpp |
diff --git a/core/src/fpdfapi/fpdf_parser/fpdf_parser_document.cpp b/core/src/fpdfapi/fpdf_parser/fpdf_parser_document.cpp |
index d8091e886193ad5069a95eb121a43fa683c620fb..6fc3440482febe3620dd6b9da69de805010a0100 100644 |
--- a/core/src/fpdfapi/fpdf_parser/fpdf_parser_document.cpp |
+++ b/core/src/fpdfapi/fpdf_parser/fpdf_parser_document.cpp |
@@ -6,7 +6,43 @@ |
#include "core/include/fpdfapi/fpdf_parser.h" |
+#include <set> |
+ |
#include "core/include/fpdfapi/fpdf_module.h" |
+#include "third_party/base/stl_util.h" |
+ |
+namespace { |
+ |
+int CountPages(CPDF_Dictionary* pPages, |
+ std::set<CPDF_Dictionary*>* visited_pages) { |
+ int count = pPages->GetInteger("Count"); |
+ if (count > 0 && count < FPDF_PAGE_MAX_NUM) { |
+ return count; |
+ } |
+ CPDF_Array* pKidList = pPages->GetArray("Kids"); |
+ if (!pKidList) { |
+ return 0; |
+ } |
+ count = 0; |
+ for (FX_DWORD i = 0; i < pKidList->GetCount(); i++) { |
+ CPDF_Dictionary* pKid = pKidList->GetDict(i); |
+ if (!pKid || pdfium::ContainsKey(*visited_pages, pKid)) { |
+ continue; |
+ } |
+ if (pKid->KeyExist("Kids")) { |
+ // Use |visited_pages| to help detect circular references of pages. |
+ ScopedSetInsertion<CPDF_Dictionary*> local_add(visited_pages, pKid); |
+ count += CountPages(pKid, visited_pages); |
+ } else { |
+ // This page is a leaf node. |
+ count++; |
+ } |
+ } |
+ pPages->SetAtInteger("Count", count); |
+ return count; |
+} |
+ |
+} // namespace |
CPDF_Document::CPDF_Document(CPDF_Parser* pParser) |
: CPDF_IndirectObjectHolder(pParser) { |
@@ -54,7 +90,7 @@ void CPDF_Document::LoadDoc() { |
m_ID1 = pIDArray->GetString(0); |
m_ID2 = pIDArray->GetString(1); |
} |
- m_PageList.SetSize(_GetPageCount()); |
+ m_PageList.SetSize(RetrievePageCount()); |
} |
void CPDF_Document::LoadAsynDoc(CPDF_Dictionary* pLinearized) { |
m_bLinearized = TRUE; |
@@ -87,7 +123,7 @@ void CPDF_Document::LoadAsynDoc(CPDF_Dictionary* pLinearized) { |
m_dwFirstPageObjNum = pObjNum->GetInteger(); |
} |
void CPDF_Document::LoadPages() { |
- m_PageList.SetSize(_GetPageCount()); |
+ m_PageList.SetSize(RetrievePageCount()); |
} |
CPDF_Document::~CPDF_Document() { |
if (m_pDocPage) { |
@@ -256,34 +292,8 @@ int CPDF_Document::GetPageIndex(FX_DWORD objnum) { |
int CPDF_Document::GetPageCount() const { |
return m_PageList.GetSize(); |
} |
-static int _CountPages(CPDF_Dictionary* pPages, int level) { |
- if (level > 128) { |
- return 0; |
- } |
- int count = pPages->GetInteger("Count"); |
- if (count > 0 && count < FPDF_PAGE_MAX_NUM) { |
- return count; |
- } |
- CPDF_Array* pKidList = pPages->GetArray("Kids"); |
- if (!pKidList) { |
- return 0; |
- } |
- count = 0; |
- for (FX_DWORD i = 0; i < pKidList->GetCount(); i++) { |
- CPDF_Dictionary* pKid = pKidList->GetDict(i); |
- if (!pKid) { |
- continue; |
- } |
- if (!pKid->KeyExist("Kids")) { |
- count++; |
- } else { |
- count += _CountPages(pKid, level + 1); |
- } |
- } |
- pPages->SetAtInteger("Count", count); |
- return count; |
-} |
-int CPDF_Document::_GetPageCount() const { |
+ |
+int CPDF_Document::RetrievePageCount() const { |
CPDF_Dictionary* pRoot = GetRoot(); |
if (!pRoot) { |
return 0; |
@@ -295,8 +305,11 @@ int CPDF_Document::_GetPageCount() const { |
if (!pPages->KeyExist("Kids")) { |
return 1; |
} |
- return _CountPages(pPages, 0); |
+ std::set<CPDF_Dictionary*> visited_pages; |
+ visited_pages.insert(pPages); |
+ return CountPages(pPages, &visited_pages); |
} |
+ |
FX_BOOL CPDF_Document::IsContentUsedElsewhere(FX_DWORD objnum, |
CPDF_Dictionary* pThisPageDict) { |
for (int i = 0; i < m_PageList.GetSize(); i++) { |