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

New commits:
commit 9a45d2779ceaa1938feddf820d826922ed17854b
Author:     Dennis Francis <[email protected]>
AuthorDate: Thu Dec 1 11:18:22 2022 +0530
Commit:     Miklos Vajna <[email protected]>
CommitDate: Wed Dec 21 07:58:38 2022 +0000

    vcl: read references to /Kids array...
    
    if the argument of /Kids is not an array.
    
    Conflicts:
            vcl/qa/cppunit/pdfexport/pdfexport.cxx
    
    Change-Id: Ib73962d3a27aa7e1ce5ddbe6845a1dd73bd7a343
    Reviewed-on: https://gerrit.libreoffice.org/c/core/+/143559
    Tested-by: Jenkins CollaboraOffice <[email protected]>
    Reviewed-by: Miklos Vajna <[email protected]>
    (cherry picked from commit 10185a6aec5d3b74a51e4b9474645e12bf794df8)
    Reviewed-on: https://gerrit.libreoffice.org/c/core/+/144434
    Tested-by: Jenkins

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 ea8f83e6ba8f..f18077505abd 100644
--- a/vcl/qa/cppunit/pdfexport/pdfexport.cxx
+++ b/vcl/qa/cppunit/pdfexport/pdfexport.cxx
@@ -15,6 +15,7 @@
 
 #include <config_features.h>
 #include <config_fonts.h>
+#include <osl/process.h>
 
 #include <com/sun/star/frame/Desktop.hpp>
 #include <com/sun/star/frame/XStorable.hpp>
@@ -4098,6 +4099,43 @@ CPPUNIT_TEST_FIXTURE(PdfExportTest, testTdf139627)
                                  / aRect[jehtatweel].getWidth());
 #endif
 }
+
+CPPUNIT_TEST_FIXTURE(PdfExportTest, testRexportRefToKids)
+{
+    // 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;
+        osl_setEnvironment(OUString("LO_IMPORT_USE_PDFIUM").pData, 
OUString("1").pData);
+    }
+    comphelper::ScopeGuard aPDFiumEnvVarGuard([&]() {
+        if (bResetEnvVar)
+            osl_clearEnvironment(OUString("LO_IMPORT_USE_PDFIUM").pData);
+    });
+
+    // 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));
+    }
+}
+
 } // end anonymous namespace
 
 CPPUNIT_PLUGIN_IMPLEMENT();
diff --git a/vcl/source/filter/ipdf/pdfdocument.cxx 
b/vcl/source/filter/ipdf/pdfdocument.cxx
index 25e731f5352a..19748e241ead 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