vcl/qa/cppunit/filter/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(+)

New commits:
commit 84d5dcc7365246352a7126ae15c54cd66bf344d9
Author:     Jaume Pujantell <jaume.pujant...@collabora.com>
AuthorDate: Fri Mar 3 19:25:11 2023 +0100
Commit:     Xisco Fauli <xiscofa...@libreoffice.org>
CommitDate: Wed Mar 8 10:58:35 2023 +0000

    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 <andras.ti...@collabora.com>
    (cherry picked from commit 574e89ccda1b389faca9f3e44d909a71b5599473)
    Reviewed-on: https://gerrit.libreoffice.org/c/core/+/148394
    Reviewed-by: Xisco Fauli <xiscofa...@libreoffice.org>

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<vcl::filter::PDFObjectElement*> aPages = aDocument.GetPages();
+    CPPUNIT_ASSERT(!aPages.empty());
+    vcl::filter::PDFObjectElement* pPage = aPages[0];
+    auto pTest = 
dynamic_cast<vcl::filter::PDFArrayElement*>(pPage->Lookup("Test"));
+    std::vector<vcl::filter::PDFElement*> 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<int>(aElements.size()));
+    CPPUNIT_ASSERT(dynamic_cast<vcl::filter::PDFNumberElement*>(aElements[0]));
+    CPPUNIT_ASSERT(dynamic_cast<vcl::filter::PDFNumberElement*>(aElements[2]));
+    CPPUNIT_ASSERT(dynamic_cast<vcl::filter::PDFNumberElement*>(aElements[4]));
+    CPPUNIT_ASSERT(dynamic_cast<vcl::filter::PDFNumberElement*>(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<PDFReferenceElement*>(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<PDFLiteralStringElement*>(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<PDFBooleanElement*>(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<PDFHexStringElement*>(pCurrentElement))
         {
+            // Handle previously stored number
+            if (!aNumbers.empty())
+            {
+                if (pParsingArray)
+                {
+                    for (auto& pNumber : aNumbers)
+                        pParsingArray->PushBack(pNumber);
+                }
+                aNumbers.clear();
+            }
+
             if (pParsingArray)
             {
                 pParsingArray->PushBack(pHexString);

Reply via email to