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..72ab12d93b312c4b1fddab982539e7463813c8a9 100644 |
--- a/core/src/fpdfapi/fpdf_parser/fpdf_parser_document.cpp |
+++ b/core/src/fpdfapi/fpdf_parser/fpdf_parser_document.cpp |
@@ -6,7 +6,42 @@ |
#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*>* counting_pages) { |
Lei Zhang
2016/01/14 19:22:39
counted_pages or encountered_pages?
Wei Li
2016/01/14 19:46:00
Those pages are not counted yet. Chose a textbook
|
+ 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(*counting_pages, pKid)) { |
+ continue; |
+ } |
+ if (!pKid->KeyExist("Kids")) { |
Lei Zhang
2016/01/14 19:22:39
Do you want to remove the '!' and flip the if/else
Wei Li
2016/01/14 19:45:59
Done.
|
+ count++; |
+ } else { |
+ // Use |counting_pages| to help detect circular references of pages. |
+ ScopedSetInsertion<CPDF_Dictionary*> local_add(counting_pages, pKid); |
+ count += CountPages(pKid, counting_pages); |
+ } |
+ } |
+ pPages->SetAtInteger("Count", count); |
+ return count; |
+} |
+ |
+} // namespace |
CPDF_Document::CPDF_Document(CPDF_Parser* pParser) |
: CPDF_IndirectObjectHolder(pParser) { |
@@ -54,7 +89,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 +122,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 +291,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 +304,11 @@ int CPDF_Document::_GetPageCount() const { |
if (!pPages->KeyExist("Kids")) { |
return 1; |
} |
- return _CountPages(pPages, 0); |
+ std::set<CPDF_Dictionary*> counting_pages; |
+ counting_pages.insert(pPages); |
+ return CountPages(pPages, &counting_pages); |
} |
+ |
FX_BOOL CPDF_Document::IsContentUsedElsewhere(FX_DWORD objnum, |
CPDF_Dictionary* pThisPageDict) { |
for (int i = 0; i < m_PageList.GetSize(); i++) { |