From 574e89ccda1b389faca9f3e44d909a71b5599473 Mon Sep 17 00:00:00 2001 From: Jaume Pujantell Date: Fri, 3 Mar 2023 19:25:11 +0100 Subject: Fix a bug parsing pdf arrays The parser ignored number elements in some situations, like before a reference element. This manifested in creating an invalid pdf file when exporting as pdf a document that contains a pdf. Change-Id: I98625c8da8631056079814f7e824f36177cf41c7 Reviewed-on: https://gerrit.libreoffice.org/c/core/+/148198 Tested-by: Jenkins Reviewed-by: Andras Timar --- .../ipdf/data/array-mixed-numbers-and-elements.pdf | 55 ++++++++++++++++++++++ vcl/qa/cppunit/filter/ipdf/ipdf.cxx | 25 ++++++++++ vcl/source/filter/ipdf/pdfdocument.cxx | 45 ++++++++++++++++++ 3 files changed, 125 insertions(+) create mode 100644 vcl/qa/cppunit/filter/ipdf/data/array-mixed-numbers-and-elements.pdf (limited to 'vcl') diff --git a/vcl/qa/cppunit/filter/ipdf/data/array-mixed-numbers-and-elements.pdf b/vcl/qa/cppunit/filter/ipdf/data/array-mixed-numbers-and-elements.pdf new file mode 100644 index 000000000000..01030ecf88bc --- /dev/null +++ b/vcl/qa/cppunit/filter/ipdf/data/array-mixed-numbers-and-elements.pdf @@ -0,0 +1,55 @@ +%PDF-1.7 +% ò¤ô +1 0 obj << + /Type /Catalog + /Pages 2 0 R +>> +endobj +2 0 obj << + /Type /Pages + /MediaBox [0 0 200 300] + /Count 1 + /Kids [3 0 R] +>> +endobj +3 0 obj << + /Type /Page + /Parent 2 0 R + /Contents 4 0 R + /Test [1 4 0 R 3 false 5 (Lieral) 7 <90>] +>> +endobj +4 0 obj << + /Length 188 +>> +stream +q +0 0 0 rg +0 290 10 10 re B* +10 150 50 30 re B* +0 0 1 rg +190 290 10 10 re B* +70 232 50 30 re B* +0 1 0 rg +190 0 10 10 re B* +130 150 50 30 re B* +1 0 0 rg +0 0 10 10 re B* +70 67 50 30 re B* +Q +endstream +endobj +xref +0 5 +0000000000 65535 f +0000000015 00000 n +0000000068 00000 n +0000000157 00000 n +0000000270 00000 n +trailer << + /Root 1 0 R + /Size 5 +>> +startxref +510 +%%EOF diff --git a/vcl/qa/cppunit/filter/ipdf/ipdf.cxx b/vcl/qa/cppunit/filter/ipdf/ipdf.cxx index 1c143a1b8319..c27555ca1d70 100644 --- a/vcl/qa/cppunit/filter/ipdf/ipdf.cxx +++ b/vcl/qa/cppunit/filter/ipdf/ipdf.cxx @@ -186,6 +186,31 @@ CPPUNIT_TEST_FIXTURE(VclFilterIpdfTest, testCommentEnd) CPPUNIT_ASSERT(aDocument.Read(aFile)); } +CPPUNIT_TEST_FIXTURE(VclFilterIpdfTest, testMixedArrayWithNumbers) +{ + // Load a file that has markup like this: + // 3 0 obj << + // /Test [1 4 0 R 3 false 5 (Lieral) 7 <90>] + // >> + OUString aSourceURL = createFileURL(u"array-mixed-numbers-and-elements.pdf"); + SvFileStream aFile(aSourceURL, StreamMode::READ); + vcl::filter::PDFDocument aDocument; + CPPUNIT_ASSERT(aDocument.Read(aFile)); + std::vector aPages = aDocument.GetPages(); + CPPUNIT_ASSERT(!aPages.empty()); + vcl::filter::PDFObjectElement* pPage = aPages[0]; + auto pTest = dynamic_cast(pPage->Lookup("Test")); + std::vector aElements = pTest->GetElements(); + + // Without the accompanying fix in place, this test would have failed with + // the array containing the wrong number of elements and in the incorrect order + CPPUNIT_ASSERT_EQUAL(8, static_cast(aElements.size())); + CPPUNIT_ASSERT(dynamic_cast(aElements[0])); + CPPUNIT_ASSERT(dynamic_cast(aElements[2])); + CPPUNIT_ASSERT(dynamic_cast(aElements[4])); + CPPUNIT_ASSERT(dynamic_cast(aElements[6])); +} + CPPUNIT_PLUGIN_IMPLEMENT(); /* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/vcl/source/filter/ipdf/pdfdocument.cxx b/vcl/source/filter/ipdf/pdfdocument.cxx index 19748e241ead..5ff50d3b55ac 100644 --- a/vcl/source/filter/ipdf/pdfdocument.cxx +++ b/vcl/source/filter/ipdf/pdfdocument.cxx @@ -3248,6 +3248,18 @@ size_t PDFObjectParser::parse(PDFElement* pParsingElement, size_t nStartIndex, i } else if (auto pReference = dynamic_cast(pCurrentElement)) { + // Handle previously stored number + if (aNumbers.size() > 2) + { + aNumbers.resize(aNumbers.size() - 2); + if (pParsingArray) + { + for (auto& pNumber : aNumbers) + pParsingArray->PushBack(pNumber); + } + aNumbers.clear(); + } + if (pParsingArray) { pParsingArray->PushBack(pReference); @@ -3268,6 +3280,17 @@ size_t PDFObjectParser::parse(PDFElement* pParsingElement, size_t nStartIndex, i } else if (auto pLiteralString = dynamic_cast(pCurrentElement)) { + // Handle previously stored number + if (!aNumbers.empty()) + { + if (pParsingArray) + { + for (auto& pNumber : aNumbers) + pParsingArray->PushBack(pNumber); + } + aNumbers.clear(); + } + if (pParsingArray) { pParsingArray->PushBack(pLiteralString); @@ -3285,6 +3308,17 @@ size_t PDFObjectParser::parse(PDFElement* pParsingElement, size_t nStartIndex, i } else if (auto pBoolean = dynamic_cast(pCurrentElement)) { + // Handle previously stored number + if (!aNumbers.empty()) + { + if (pParsingArray) + { + for (auto& pNumber : aNumbers) + pParsingArray->PushBack(pNumber); + } + aNumbers.clear(); + } + if (pParsingArray) { pParsingArray->PushBack(pBoolean); @@ -3302,6 +3336,17 @@ size_t PDFObjectParser::parse(PDFElement* pParsingElement, size_t nStartIndex, i } else if (auto pHexString = dynamic_cast(pCurrentElement)) { + // Handle previously stored number + if (!aNumbers.empty()) + { + if (pParsingArray) + { + for (auto& pNumber : aNumbers) + pParsingArray->PushBack(pNumber); + } + aNumbers.clear(); + } + if (pParsingArray) { pParsingArray->PushBack(pHexString); -- cgit