From 8a9cfd2605dc6754d92b7b0ab849e082b77a78ae Mon Sep 17 00:00:00 2001 From: Jay Berkenbilt Date: Tue, 29 Jan 2019 17:01:36 -0500 Subject: [PATCH] Handle direct page objects (fixes #164) --- ChangeLog | 5 ++ libqpdf/QPDF_pages.cc | 8 +- qpdf/qpdf.testcov | 1 + qpdf/qtest/qpdf.test | 15 +++- qpdf/qtest/qpdf/direct-pages-fixed.pdf | Bin 0 -> 968 bytes qpdf/qtest/qpdf/direct-pages.out | 6 ++ qpdf/qtest/qpdf/direct-pages.pdf | 111 +++++++++++++++++++++++++ 7 files changed, 144 insertions(+), 2 deletions(-) create mode 100644 qpdf/qtest/qpdf/direct-pages-fixed.pdf create mode 100644 qpdf/qtest/qpdf/direct-pages.out create mode 100644 qpdf/qtest/qpdf/direct-pages.pdf diff --git a/ChangeLog b/ChangeLog index 180335f6..861ff64c 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,8 @@ +2019-01-29 Jay Berkenbilt + + * Handle files with direct page objects, which is not allowed by + the PDF spec but has been seen in the wild. Fixes #164. + 2019-01-28 Jay Berkenbilt * Bug fix: when using --stream-data=compress, object streams and diff --git a/libqpdf/QPDF_pages.cc b/libqpdf/QPDF_pages.cc index 397c175a..01270652 100644 --- a/libqpdf/QPDF_pages.cc +++ b/libqpdf/QPDF_pages.cc @@ -105,7 +105,13 @@ QPDF::getAllPagesInternal3(QPDFObjectHandle cur_pages, for (int i = 0; i < n; ++i) { QPDFObjectHandle kid = kids.getArrayItem(i); - if (seen.count(kid.getObjGen())) + if (! kid.isIndirect()) + { + QTC::TC("qpdf", "QPDF handle direct page object"); + kid = makeIndirectObject(kid); + kids.setArrayItem(i, kid); + } + else if (seen.count(kid.getObjGen())) { // Make a copy of the page. This does the same as // shallowCopyPage in QPDFPageObjectHelper. diff --git a/qpdf/qpdf.testcov b/qpdf/qpdf.testcov index 98857597..5150e567 100644 --- a/qpdf/qpdf.testcov +++ b/qpdf/qpdf.testcov @@ -429,3 +429,4 @@ QPDFPageObjectHelper non-trivial inheritance 0 QPDFPageObjectHelper copy shared attribute 0 qpdf from_nr from repeat_nr 0 QPDF resolve duplicated page object 0 +QPDF handle direct page object 0 diff --git a/qpdf/qtest/qpdf.test b/qpdf/qtest/qpdf.test index 85b9b8de..ca7ea12b 100644 --- a/qpdf/qtest/qpdf.test +++ b/qpdf/qtest/qpdf.test @@ -2461,7 +2461,7 @@ for (my $n = 16; $n <= 19; ++$n) show_ntests(); # ---------- $td->notify("--- Specific File Tests ---"); -$n_tests += 4; +$n_tests += 7; # Special PDF files that caused problems at some point @@ -2482,6 +2482,19 @@ $td->runtest("compress objstm and xref", $td->runtest("check output", {$td->FILE => "a.pdf"}, {$td->FILE => "compress-objstm-xref.pdf"}); +$td->runtest("direct pages", + {$td->COMMAND => + "qpdf --static-id direct-pages.pdf --pages . -- a.pdf"}, + {$td->STRING => "", $td->EXIT_STATUS => 0}, + $td->NORMALIZE_NEWLINES); +$td->runtest("check output", + {$td->FILE => "a.pdf"}, + {$td->FILE => "direct-pages-fixed.pdf"}); +$td->runtest("show direct pages", + {$td->COMMAND => + "qpdf --show-pages direct-pages.pdf"}, + {$td->FILE => "direct-pages.out", $td->EXIT_STATUS => 0}, + $td->NORMALIZE_NEWLINES); show_ntests(); # ---------- diff --git a/qpdf/qtest/qpdf/direct-pages-fixed.pdf b/qpdf/qtest/qpdf/direct-pages-fixed.pdf new file mode 100644 index 0000000000000000000000000000000000000000..ab577e8c008a03c7f91a70e74bf86ad6258aab49 GIT binary patch literal 968 zcmd5*OODe(5alDJ&=PkjB(ekAcH3=RiY%DPSVa6n5{X5WMUT@Hj6B`Q?#u*MT!0&} z;s{)TZAJ)*6|9F#utQWk;}``FfGzp+y6SaRz1Q7gKfUALWu*J*=Z9a!1qbxuOVaBB z9g2mlz(ZsNbn^O@1iCMbDD(o7gh(~Ffp)n`*w;&CFo8bI=M_wW)v12{oHZ01)|S8q zwFJsYWhw~j9Qs(!bFrsa$mQV8T@S+81LPWt5(As!MzYe&GQ(+nM zMb1aVucvI{c+Wb6s~^9-d%M1O^VYTXx6YalZl8Uhbk2U1H_oqI`h5BN8l}9*yb#q+ zt=V-?RI;8ZeISbyY4S_}Jy5u1t`frvQU3wRK)0FGdbxi}1XF+TFS$9={k=7n*P%&b)_BT7?`hKCO6b`PGW> +endobj + +%% Original object ID: 2 0 +2 0 obj +<< + /Count 2 + /Kids [ + << + /Contents 3 0 R + /MediaBox [ + 0 + 0 + 612 + 792 + ] + /Parent 2 0 R + /Resources << + /Font << + /F1 5 0 R + >> + /ProcSet 6 0 R + >> + /Type /Page + >> + << + /Contents 3 0 R + /MediaBox [ + 0 + 0 + 612 + 792 + ] + /Parent 2 0 R + /Resources << + /Font << + /F1 5 0 R + >> + /ProcSet 6 0 R + >> + /Type /Page + >> + ] + /Type /Pages +>> +endobj + +%% Contents for page 2 +%% Original object ID: 4 0 +3 0 obj +<< + /Length 4 0 R +>> +stream +BT + /F1 24 Tf + 72 720 Td + (Potato) Tj +ET +endstream +endobj + +4 0 obj +44 +endobj + +%% Original object ID: 6 0 +5 0 obj +<< + /BaseFont /Helvetica + /Encoding /WinAnsiEncoding + /Name /F1 + /Subtype /Type1 + /Type /Font +>> +endobj + +%% Original object ID: 7 0 +6 0 obj +[ + /PDF + /Text +] +endobj + +xref +0 7 +0000000000 65535 f +0000000052 00000 n +0000000133 00000 n +0000000733 00000 n +0000000832 00000 n +0000000878 00000 n +0000001023 00000 n +trailer << + /Root 1 0 R + /Size 7 + /ID [<1323a5937c577a66735583a93698ce3c><372cbf44f6db88ab60d9263c0f0bd26a>] +>> +startxref +1058 +%%EOF