vcl/qa/cppunit/pdfexport/data/ref-to-kids.pdf |binary
 vcl/qa/cppunit/pdfexport/pdfexport.cxx        |   40 ++++++++++++++++++++++++++
 vcl/source/filter/ipdf/pdfdocument.cxx        |   21 +++++++++++++
 3 files changed, 60 insertions(+), 1 deletion(-)

New commits:
commit 10185a6aec5d3b74a51e4b9474645e12bf794df8
Author:     Dennis Francis <dennis.fran...@collabora.com>
AuthorDate: Thu Dec 1 11:18:22 2022 +0530
Commit:     Miklos Vajna <vmik...@collabora.com>
CommitDate: Fri Dec 16 13:38:14 2022 +0000

    vcl: read references to /Kids array...
    
    if the argument of /Kids is not an array.
    
    Change-Id: Ib73962d3a27aa7e1ce5ddbe6845a1dd73bd7a343
    Reviewed-on: https://gerrit.libreoffice.org/c/core/+/143559
    Tested-by: Jenkins CollaboraOffice <jenkinscollaboraoff...@gmail.com>
    Reviewed-by: Miklos Vajna <vmik...@collabora.com>

diff --git a/vcl/qa/cppunit/pdfexport/data/ref-to-kids.pdf 
b/vcl/qa/cppunit/pdfexport/data/ref-to-kids.pdf
new file mode 100644
index 000000000000..598358a636aa
Binary files /dev/null and b/vcl/qa/cppunit/pdfexport/data/ref-to-kids.pdf 
differ
diff --git a/vcl/qa/cppunit/pdfexport/pdfexport.cxx 
b/vcl/qa/cppunit/pdfexport/pdfexport.cxx
index df0fea74db6f..b6b6ba7f7fc0 100644
--- a/vcl/qa/cppunit/pdfexport/pdfexport.cxx
+++ b/vcl/qa/cppunit/pdfexport/pdfexport.cxx
@@ -3346,6 +3346,46 @@ CPPUNIT_TEST_FIXTURE(PdfExportTest, testBitmapScaledown)
     }
 }
 
+CPPUNIT_TEST_FIXTURE(PdfExportTest, testRexportRefToKids)
+{
+// setenv only works on unix based systems
+#ifndef _WIN32
+    // We need to enable PDFium import (and make sure to disable after the 
test)
+    bool bResetEnvVar = false;
+    if (getenv("LO_IMPORT_USE_PDFIUM") == nullptr)
+    {
+        bResetEnvVar = true;
+        setenv("LO_IMPORT_USE_PDFIUM", "1", false);
+    }
+    comphelper::ScopeGuard aPDFiumEnvVarGuard([&]() {
+        if (bResetEnvVar)
+            unsetenv("LO_IMPORT_USE_PDFIUM");
+    });
+
+    // Load the PDF and save as PDF
+    vcl::filter::PDFDocument aDocument;
+    load(u"ref-to-kids.pdf", aDocument);
+
+    std::vector<vcl::filter::PDFObjectElement*> aPages = aDocument.GetPages();
+    CPPUNIT_ASSERT_EQUAL(size_t(5), aPages.size());
+
+    vcl::filter::PDFObjectElement* pResources = 
aPages[0]->LookupObject("Resources");
+    CPPUNIT_ASSERT(pResources);
+
+    auto pXObjects
+        = 
dynamic_cast<vcl::filter::PDFDictionaryElement*>(pResources->Lookup("XObject"));
+    CPPUNIT_ASSERT(pXObjects);
+
+    // Without the fix LookupObject for all /Im's will fail.
+    for (auto const& rPair : pXObjects->GetItems())
+    {
+        if (rPair.first.startsWith("Im"))
+            CPPUNIT_ASSERT(pXObjects->LookupObject(rPair.first));
+    }
+
+#endif
+}
+
 } // end anonymous namespace
 
 CPPUNIT_PLUGIN_IMPLEMENT();
diff --git a/vcl/source/filter/ipdf/pdfdocument.cxx 
b/vcl/source/filter/ipdf/pdfdocument.cxx
index 4430c7217fc7..9ef202ee132b 100644
--- a/vcl/source/filter/ipdf/pdfdocument.cxx
+++ b/vcl/source/filter/ipdf/pdfdocument.cxx
@@ -1918,7 +1918,26 @@ const std::vector<std::unique_ptr<PDFElement>>& 
PDFDocument::GetElements() const
 /// Visits the page tree recursively, looking for page objects.
 static void visitPages(PDFObjectElement* pPages, 
std::vector<PDFObjectElement*>& rRet)
 {
-    auto pKids = dynamic_cast<PDFArrayElement*>(pPages->Lookup("Kids"));
+    auto pKidsRef = pPages->Lookup("Kids");
+    auto pKids = dynamic_cast<PDFArrayElement*>(pKidsRef);
+    if (!pKids)
+    {
+        auto pRefKids = dynamic_cast<PDFReferenceElement*>(pKidsRef);
+        if (!pRefKids)
+        {
+            SAL_WARN("vcl.filter", "visitPages: pages has no kids");
+            return;
+        }
+        auto pObjWithKids = pRefKids->LookupObject();
+        if (!pObjWithKids)
+        {
+            SAL_WARN("vcl.filter", "visitPages: pages has no kids");
+            return;
+        }
+
+        pKids = pObjWithKids->GetArray();
+    }
+
     if (!pKids)
     {
         SAL_WARN("vcl.filter", "visitPages: pages has no kids");

Reply via email to