Add a null check on return value of CPDF_StructTree::AddPageNode(). This CL Adds a null check for |pParentElement| before usage inside AddPageNode(). This ensures that the code handles the scenario when AddPageNode() returns nullptr if depth is greater than kStructTreeMaxRecursion(= 32). This CL also includes a test tagged PDF with deeply nested tags(nested depth > 33). The file is used to validate if struct tree is loaded for this file. Bug: pdfium:1480 Change-Id: I66c561d6708f8d89a0616eb7adef8459ae952662 Reviewed-on: https://pdfium-review.googlesource.com/c/pdfium/+/66110 Reviewed-by: Lei Zhang <thestig@chromium.org> Commit-Queue: Mansi Awasthi <maawas@microsoft.com>
diff --git a/core/fpdfdoc/cpdf_structtree.cpp b/core/fpdfdoc/cpdf_structtree.cpp index 8fd43e2..4976d43 100644 --- a/core/fpdfdoc/cpdf_structtree.cpp +++ b/core/fpdfdoc/cpdf_structtree.cpp
@@ -105,6 +105,9 @@ RetainPtr<CPDF_StructElement> pParentElement = AddPageNode(pParent, map, nLevel + 1); + if (!pParentElement) + return pElement; + bool bSave = false; for (CPDF_StructKid& kid : *pParentElement->GetKids()) { if (kid.m_Type == CPDF_StructKid::kElement && kid.m_pDict == pDict) {
diff --git a/fpdfsdk/fpdf_structtree_embeddertest.cpp b/fpdfsdk/fpdf_structtree_embeddertest.cpp index bbaa115..21cbffd 100644 --- a/fpdfsdk/fpdf_structtree_embeddertest.cpp +++ b/fpdfsdk/fpdf_structtree_embeddertest.cpp
@@ -177,3 +177,16 @@ UnloadPage(page); } + +TEST_F(FPDFStructTreeEmbedderTest, GetStructTreeForNestedTaggedPDF) { + ASSERT_TRUE(OpenDocument("tagged_nested.pdf")); + FPDF_PAGE page = LoadPage(0); + ASSERT_TRUE(page); + + { + // This call should not crash. https://crbug.com/pdfium/1480 + ScopedFPDFStructTree struct_tree(FPDF_StructTree_GetForPage(page)); + ASSERT_TRUE(struct_tree); + } + UnloadPage(page); +}
diff --git a/testing/resources/tagged_nested.in b/testing/resources/tagged_nested.in new file mode 100644 index 0000000..b7d2022 --- /dev/null +++ b/testing/resources/tagged_nested.in
@@ -0,0 +1,346 @@ +{{header}} +{{object 1 0}} << + /Type /Catalog + /Pages 2 0 R + /StructTreeRoot 5 0 R + /Lang (en-US) + /MarkInfo << + /Marked true + >> +>> +endobj +{{object 2 0}} << + /Type /Pages + /Count 1 + /Kids [3 0 R] +>> +endobj +{{object 3 0}} << + /Type /Page + /Parent 2 0 R + /Contents 4 0 R + /MediaBox [0 0 612 792] + /StructParents 0 +>> +endobj +{{object 4 0}} << + {{streamlen}} +>> +stream +BT +/Para<</MCID 0>> +BMC +0 0 Td +/F1 18 Tf +(Sample Text) Tj +EMC +ET +endstream +endobj +{{object 5 0}} << + /Type /StructTreeRoot + /ParentTree 6 0 R + /K [8 0 R] + /RoleMap << + /Document /Document + /Para /Para + >> +>> +endobj +{{object 6 0}} << + /Nums [0 [7 0 R]] +>> +endobj +{{object 7 0}} << + /Type /StructElem + /S /Para + /K [0] + /P 42 0 R + /Pg 3 0 R +>> +endobj +{{object 8 0}} << + /Type /StructElem + /S /Document + /K [9 0 R] + /P 5 0 R + /T (TitleText) + /Pg 3 0 R +>> +endobj +{{object 9 0}} << + /Type /StructElem + /S /Para + /K [10 0 R] + /P 8 0 R + /Pg 3 0 R +>> +endobj +{{object 10 0}} << + /Type /StructElem + /S /Para + /K [11 0 R] + /P 9 0 R + /Pg 3 0 R +>> +endobj +{{object 11 0}} << + /Type /StructElem + /S /Para + /K [12 0 R] + /P 10 0 R + /Pg 3 0 R +>> +endobj +{{object 12 0}} << + /Type /StructElem + /S /Para + /K [13 0 R] + /P 11 0 R + /Pg 3 0 R +>> +endobj +{{object 13 0}} << + /Type /StructElem + /S /Para + /K [14 0 R] + /P 12 0 R + /Pg 3 0 R +>> +endobj +{{object 14 0}} << + /Type /StructElem + /S /Para + /K [15 0 R] + /P 13 0 R + /Pg 3 0 R +>> +endobj +{{object 15 0}} << + /Type /StructElem + /S /Para + /K [16 0 R] + /P 14 0 R + /Pg 3 0 R +>> +endobj +{{object 16 0}} << + /Type /StructElem + /S /Para + /K [17 0 R] + /P 15 0 R + /Pg 3 0 R +>> +endobj +{{object 17 0}} << + /Type /StructElem + /S /Para + /K [18 0 R] + /P 16 0 R + /Pg 3 0 R +>> +endobj +{{object 18 0}} << + /Type /StructElem + /S /Para + /K [19 0 R] + /P 17 0 R + /Pg 3 0 R +>> +endobj +{{object 19 0}} << + /Type /StructElem + /S /Para + /K [20 0 R] + /P 18 0 R + /Pg 3 0 R +>> +endobj +{{object 20 0}} << + /Type /StructElem + /S /Para + /K [21 0 R] + /P 19 0 R + /Pg 3 0 R +>> +endobj +{{object 21 0}} << + /Type /StructElem + /S /Para + /K [22 0 R] + /P 20 0 R + /Pg 3 0 R +>> +endobj +{{object 22 0}} << + /Type /StructElem + /S /Para + /K [23 0 R] + /P 21 0 R + /Pg 3 0 R +>> +endobj +{{object 23 0}} << + /Type /StructElem + /S /Para + /K [24 0 R] + /P 22 0 R + /Pg 3 0 R +>> +endobj +{{object 24 0}} << + /Type /StructElem + /S /Para + /K [25 0 R] + /P 23 0 R + /Pg 3 0 R +>> +endobj +{{object 25 0}} << + /Type /StructElem + /S /Para + /K [26 0 R] + /P 24 0 R + /Pg 3 0 R +>> +endobj +{{object 26 0}} << + /Type /StructElem + /S /Para + /K [27 0 R] + /P 25 0 R + /Pg 3 0 R +>> +endobj +{{object 27 0}} << + /Type /StructElem + /S /Para + /K [28 0 R] + /P 26 0 R + /Pg 3 0 R +>> +endobj +{{object 28 0}} << + /Type /StructElem + /S /Para + /K [29 0 R] + /P 27 0 R + /Pg 3 0 R +>> +endobj +{{object 29 0}} << + /Type /StructElem + /S /Para + /K [30 0 R] + /P 28 0 R + /Pg 3 0 R +>> +endobj +{{object 30 0}} << + /Type /StructElem + /S /Para + /K [31 0 R] + /P 29 0 R + /Pg 3 0 R +>> +endobj +{{object 31 0}} << + /Type /StructElem + /S /Para + /K [32 0 R] + /P 30 0 R + /Pg 3 0 R +>> +endobj +{{object 32 0}} << + /Type /StructElem + /S /Para + /K [33 0 R] + /P 31 0 R + /Pg 3 0 R +>> +endobj +{{object 33 0}} << + /Type /StructElem + /S /Para + /K [34 0 R] + /P 32 0 R + /Pg 3 0 R +>> +endobj +{{object 34 0}} << + /Type /StructElem + /S /Para + /K [35 0 R] + /P 33 0 R + /Pg 3 0 R +>> +endobj +{{object 35 0}} << + /Type /StructElem + /S /Para + /K [36 0 R] + /P 34 0 R + /Pg 3 0 R +>> +endobj +{{object 36 0}} << + /Type /StructElem + /S /Para + /K [37 0 R] + /P 35 0 R + /Pg 3 0 R +>> +endobj +{{object 37 0}} << + /Type /StructElem + /S /Para + /K [38 0 R] + /P 36 0 R + /Pg 3 0 R +>> +endobj +{{object 38 0}} << + /Type /StructElem + /S /Para + /K [39 0 R] + /P 37 0 R + /Pg 3 0 R +>> +endobj +{{object 39 0}} << + /Type /StructElem + /S /Para + /K [40 0 R] + /P 38 0 R + /Pg 3 0 R +>> +endobj +{{object 40 0}} << + /Type /StructElem + /S /Para + /K [41 0 R] + /P 39 0 R + /Pg 3 0 R +>> +endobj +{{object 41 0}} << + /Type /StructElem + /S /Para + /K [42 0 R] + /P 40 0 R + /Pg 3 0 R +>> +endobj +{{object 42 0}} << + /Type /StructElem + /S /Para + /K [7 0 R] + /P 41 0 R + /Pg 3 0 R +>> +endobj +{{xref}} +{{trailer}} +{{startxref}} +%%EOF
diff --git a/testing/resources/tagged_nested.pdf b/testing/resources/tagged_nested.pdf new file mode 100644 index 0000000..8e09360 --- /dev/null +++ b/testing/resources/tagged_nested.pdf
@@ -0,0 +1,395 @@ +%PDF-1.7 +% ò¤ô +1 0 obj << + /Type /Catalog + /Pages 2 0 R + /StructTreeRoot 5 0 R + /Lang (en-US) + /MarkInfo << + /Marked true + >> +>> +endobj +2 0 obj << + /Type /Pages + /Count 1 + /Kids [3 0 R] +>> +endobj +3 0 obj << + /Type /Page + /Parent 2 0 R + /Contents 4 0 R + /MediaBox [0 0 612 792] + /StructParents 0 +>> +endobj +4 0 obj << + /Length 65 +>> +stream +BT +/Para<</MCID 0>> +BMC +0 0 Td +/F1 18 Tf +(Sample Text) Tj +EMC +ET +endstream +endobj +5 0 obj << + /Type /StructTreeRoot + /ParentTree 6 0 R + /K [8 0 R] + /RoleMap << + /Document /Document + /Para /Para + >> +>> +endobj +6 0 obj << + /Nums [0 [7 0 R]] +>> +endobj +7 0 obj << + /Type /StructElem + /S /Para + /K [0] + /P 42 0 R + /Pg 3 0 R +>> +endobj +8 0 obj << + /Type /StructElem + /S /Document + /K [9 0 R] + /P 5 0 R + /T (TitleText) + /Pg 3 0 R +>> +endobj +9 0 obj << + /Type /StructElem + /S /Para + /K [10 0 R] + /P 8 0 R + /Pg 3 0 R +>> +endobj +10 0 obj << + /Type /StructElem + /S /Para + /K [11 0 R] + /P 9 0 R + /Pg 3 0 R +>> +endobj +11 0 obj << + /Type /StructElem + /S /Para + /K [12 0 R] + /P 10 0 R + /Pg 3 0 R +>> +endobj +12 0 obj << + /Type /StructElem + /S /Para + /K [13 0 R] + /P 11 0 R + /Pg 3 0 R +>> +endobj +13 0 obj << + /Type /StructElem + /S /Para + /K [14 0 R] + /P 12 0 R + /Pg 3 0 R +>> +endobj +14 0 obj << + /Type /StructElem + /S /Para + /K [15 0 R] + /P 13 0 R + /Pg 3 0 R +>> +endobj +15 0 obj << + /Type /StructElem + /S /Para + /K [16 0 R] + /P 14 0 R + /Pg 3 0 R +>> +endobj +16 0 obj << + /Type /StructElem + /S /Para + /K [17 0 R] + /P 15 0 R + /Pg 3 0 R +>> +endobj +17 0 obj << + /Type /StructElem + /S /Para + /K [18 0 R] + /P 16 0 R + /Pg 3 0 R +>> +endobj +18 0 obj << + /Type /StructElem + /S /Para + /K [19 0 R] + /P 17 0 R + /Pg 3 0 R +>> +endobj +19 0 obj << + /Type /StructElem + /S /Para + /K [20 0 R] + /P 18 0 R + /Pg 3 0 R +>> +endobj +20 0 obj << + /Type /StructElem + /S /Para + /K [21 0 R] + /P 19 0 R + /Pg 3 0 R +>> +endobj +21 0 obj << + /Type /StructElem + /S /Para + /K [22 0 R] + /P 20 0 R + /Pg 3 0 R +>> +endobj +22 0 obj << + /Type /StructElem + /S /Para + /K [23 0 R] + /P 21 0 R + /Pg 3 0 R +>> +endobj +23 0 obj << + /Type /StructElem + /S /Para + /K [24 0 R] + /P 22 0 R + /Pg 3 0 R +>> +endobj +24 0 obj << + /Type /StructElem + /S /Para + /K [25 0 R] + /P 23 0 R + /Pg 3 0 R +>> +endobj +25 0 obj << + /Type /StructElem + /S /Para + /K [26 0 R] + /P 24 0 R + /Pg 3 0 R +>> +endobj +26 0 obj << + /Type /StructElem + /S /Para + /K [27 0 R] + /P 25 0 R + /Pg 3 0 R +>> +endobj +27 0 obj << + /Type /StructElem + /S /Para + /K [28 0 R] + /P 26 0 R + /Pg 3 0 R +>> +endobj +28 0 obj << + /Type /StructElem + /S /Para + /K [29 0 R] + /P 27 0 R + /Pg 3 0 R +>> +endobj +29 0 obj << + /Type /StructElem + /S /Para + /K [30 0 R] + /P 28 0 R + /Pg 3 0 R +>> +endobj +30 0 obj << + /Type /StructElem + /S /Para + /K [31 0 R] + /P 29 0 R + /Pg 3 0 R +>> +endobj +31 0 obj << + /Type /StructElem + /S /Para + /K [32 0 R] + /P 30 0 R + /Pg 3 0 R +>> +endobj +32 0 obj << + /Type /StructElem + /S /Para + /K [33 0 R] + /P 31 0 R + /Pg 3 0 R +>> +endobj +33 0 obj << + /Type /StructElem + /S /Para + /K [34 0 R] + /P 32 0 R + /Pg 3 0 R +>> +endobj +34 0 obj << + /Type /StructElem + /S /Para + /K [35 0 R] + /P 33 0 R + /Pg 3 0 R +>> +endobj +35 0 obj << + /Type /StructElem + /S /Para + /K [36 0 R] + /P 34 0 R + /Pg 3 0 R +>> +endobj +36 0 obj << + /Type /StructElem + /S /Para + /K [37 0 R] + /P 35 0 R + /Pg 3 0 R +>> +endobj +37 0 obj << + /Type /StructElem + /S /Para + /K [38 0 R] + /P 36 0 R + /Pg 3 0 R +>> +endobj +38 0 obj << + /Type /StructElem + /S /Para + /K [39 0 R] + /P 37 0 R + /Pg 3 0 R +>> +endobj +39 0 obj << + /Type /StructElem + /S /Para + /K [40 0 R] + /P 38 0 R + /Pg 3 0 R +>> +endobj +40 0 obj << + /Type /StructElem + /S /Para + /K [41 0 R] + /P 39 0 R + /Pg 3 0 R +>> +endobj +41 0 obj << + /Type /StructElem + /S /Para + /K [42 0 R] + /P 40 0 R + /Pg 3 0 R +>> +endobj +42 0 obj << + /Type /StructElem + /S /Para + /K [7 0 R] + /P 41 0 R + /Pg 3 0 R +>> +endobj +xref +0 43 +0000000000 65535 f +0000000015 00000 n +0000000145 00000 n +0000000208 00000 n +0000000322 00000 n +0000000438 00000 n +0000000575 00000 n +0000000616 00000 n +0000000701 00000 n +0000000810 00000 n +0000000899 00000 n +0000000989 00000 n +0000001080 00000 n +0000001171 00000 n +0000001262 00000 n +0000001353 00000 n +0000001444 00000 n +0000001535 00000 n +0000001626 00000 n +0000001717 00000 n +0000001808 00000 n +0000001899 00000 n +0000001990 00000 n +0000002081 00000 n +0000002172 00000 n +0000002263 00000 n +0000002354 00000 n +0000002445 00000 n +0000002536 00000 n +0000002627 00000 n +0000002718 00000 n +0000002809 00000 n +0000002900 00000 n +0000002991 00000 n +0000003082 00000 n +0000003173 00000 n +0000003264 00000 n +0000003355 00000 n +0000003446 00000 n +0000003537 00000 n +0000003628 00000 n +0000003719 00000 n +0000003810 00000 n +trailer << + /Root 1 0 R + /Size 43 +>> +startxref +3900 +%%EOF