summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--core/src/fpdfapi/fpdf_parser/fpdf_parser_parser.cpp14
-rw-r--r--core/src/fpdfapi/fpdf_parser/fpdf_parser_parser_embeddertest.cpp9
-rw-r--r--testing/resources/bug_544880.in19
-rw-r--r--testing/resources/bug_544880.pdf25
4 files changed, 63 insertions, 4 deletions
diff --git a/core/src/fpdfapi/fpdf_parser/fpdf_parser_parser.cpp b/core/src/fpdfapi/fpdf_parser/fpdf_parser_parser.cpp
index 5de4a41fe1..fe8975fba0 100644
--- a/core/src/fpdfapi/fpdf_parser/fpdf_parser_parser.cpp
+++ b/core/src/fpdfapi/fpdf_parser/fpdf_parser_parser.cpp
@@ -2760,6 +2760,7 @@ class CPDF_DataAvail final : public IPDF_DataAvail {
protected:
static const int kMaxDataAvailRecursionDepth = 64;
static int s_CurrentDataAvailRecursionDepth;
+ static const int kMaxPageRecursionDepth = 1024;
FX_DWORD GetObjectSize(FX_DWORD objnum, FX_FILESIZE& offset);
FX_BOOL IsObjectsAvail(CFX_PtrArray& obj_array,
@@ -2812,7 +2813,8 @@ class CPDF_DataAvail final : public IPDF_DataAvail {
FX_BOOL CheckPageNode(CPDF_PageNode& pageNodes,
int32_t iPage,
int32_t& iCount,
- IFX_DownloadHints* pHints);
+ IFX_DownloadHints* pHints,
+ int level);
FX_BOOL CheckUnkownPageNode(FX_DWORD dwPageNo,
CPDF_PageNode* pPageNode,
IFX_DownloadHints* pHints);
@@ -4199,7 +4201,11 @@ FX_BOOL CPDF_DataAvail::CheckUnkownPageNode(FX_DWORD dwPageNo,
FX_BOOL CPDF_DataAvail::CheckPageNode(CPDF_PageNode& pageNodes,
int32_t iPage,
int32_t& iCount,
- IFX_DownloadHints* pHints) {
+ IFX_DownloadHints* pHints,
+ int level) {
+ if (level >= kMaxPageRecursionDepth) {
+ return FALSE;
+ }
int32_t iSize = pageNodes.m_childNode.GetSize();
if (iSize <= 0 || iPage >= iSize) {
m_docStatus = PDF_DATAAVAIL_ERROR;
@@ -4224,7 +4230,7 @@ FX_BOOL CPDF_DataAvail::CheckPageNode(CPDF_PageNode& pageNodes,
}
break;
case PDF_PAGENODE_PAGES:
- if (!CheckPageNode(*pNode, iPage, iCount, pHints)) {
+ if (!CheckPageNode(*pNode, iPage, iCount, pHints, level + 1)) {
return FALSE;
}
break;
@@ -4257,7 +4263,7 @@ FX_BOOL CPDF_DataAvail::LoadDocPage(int32_t iPage, IFX_DownloadHints* pHints) {
return TRUE;
}
int32_t iCount = -1;
- return CheckPageNode(m_pageNodes, iPage, iCount, pHints);
+ return CheckPageNode(m_pageNodes, iPage, iCount, pHints, 0);
}
FX_BOOL CPDF_DataAvail::CheckPageCount(IFX_DownloadHints* pHints) {
FX_BOOL bExist = FALSE;
diff --git a/core/src/fpdfapi/fpdf_parser/fpdf_parser_parser_embeddertest.cpp b/core/src/fpdfapi/fpdf_parser/fpdf_parser_parser_embeddertest.cpp
index 96ea766d4d..b6cfc4e89f 100644
--- a/core/src/fpdfapi/fpdf_parser/fpdf_parser_parser_embeddertest.cpp
+++ b/core/src/fpdfapi/fpdf_parser/fpdf_parser_parser_embeddertest.cpp
@@ -19,3 +19,12 @@ TEST_F(FPDFParserEmbeddertest, Bug_481363) {
EXPECT_NE(nullptr, page);
UnloadPage(page);
}
+
+TEST_F(FPDFParserEmbeddertest, Bug_544880) {
+ // Test self referencing /Pages object.
+ EXPECT_TRUE(OpenDocument("testing/resources/bug_544880.pdf"));
+ // Shouldn't crash. We don't check the return value here because we get the
+ // the count from the "/Count 1" in the testcase (at the time of writing)
+ // rather than the actual count (0).
+ (void)GetPageCount();
+}
diff --git a/testing/resources/bug_544880.in b/testing/resources/bug_544880.in
new file mode 100644
index 0000000000..926a491d91
--- /dev/null
+++ b/testing/resources/bug_544880.in
@@ -0,0 +1,19 @@
+{{header}}
+{{object 1 0}} <<
+ /Type /Catalog
+ /Pages 2 0 R
+>>
+endobj
+{{object 2 0}} <<
+ /Type /Pages
+ /Count 1
+ /Kids [2 0 R]
+>>
+endobj
+{{xref}}
+trailer <<
+ /Size 3
+ /Root 1 0 R
+>>
+{{startxref}}
+%%EOF
diff --git a/testing/resources/bug_544880.pdf b/testing/resources/bug_544880.pdf
new file mode 100644
index 0000000000..4a8e5b9904
--- /dev/null
+++ b/testing/resources/bug_544880.pdf
@@ -0,0 +1,25 @@
+%PDF-1.7
+% ò¤ô
+1 0 obj <<
+ /Type /Catalog
+ /Pages 2 0 R
+>>
+endobj
+2 0 obj <<
+ /Type /Pages
+ /Count 1
+ /Kids [2 0 R]
+>>
+endobj
+xref
+0 3
+0000000000 65535 f
+0000000015 00000 n
+0000000068 00000 n
+trailer <<
+ /Size 3
+ /Root 1 0 R
+>>
+startxref
+131
+%%EOF