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");