diff --git a/ChangeLog b/ChangeLog index efb2173a..24bbc569 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,8 @@ +2021-11-03 Jay Berkenbilt + + * Bug fix: make overlay/underlay work on a page with no resource + dictionary. Fixes #527. + 2021-11-02 Jay Berkenbilt * Add QPDF::findPage to the public API. This is primarily to help diff --git a/manual/qpdf-manual.xml b/manual/qpdf-manual.xml index 8924dc51..7cd22459 100644 --- a/manual/qpdf-manual.xml +++ b/manual/qpdf-manual.xml @@ -5080,6 +5080,12 @@ print "\n"; that could occur when given bogus input. + + + Properly handle overlay/underlay on completely empty pages + (with no resource dictionary). + + diff --git a/qpdf/qpdf.cc b/qpdf/qpdf.cc index 2ed03cff..e1cd62da 100644 --- a/qpdf/qpdf.cc +++ b/qpdf/qpdf.cc @@ -5226,6 +5226,12 @@ static void do_under_overlay_for_page( std::string content; int min_suffix = 1; QPDFObjectHandle resources = dest_page.getAttribute("/Resources", true); + if (! resources.isDictionary()) + { + QTC::TC("qpdf", "qpdf overlay page with no resources"); + resources = QPDFObjectHandle::newDictionary(); + dest_page.getObjectHandle().replaceKey("/Resources", resources); + } for (std::vector::iterator iter = pagenos[pageno].begin(); iter != pagenos[pageno].end(); ++iter) { @@ -5257,7 +5263,11 @@ static void do_under_overlay_for_page( { resources.mergeResources( QPDFObjectHandle::parse("<< /XObject << >> >>")); - resources.getKey("/XObject").replaceKey(name, fo[from_pageno]); + auto xobject = resources.getKey("/XObject"); + if (xobject.isDictionary()) + { + xobject.replaceKey(name, fo[from_pageno]); + } ++min_suffix; content += new_content; } diff --git a/qpdf/qpdf.testcov b/qpdf/qpdf.testcov index 0cb56525..68a32d43 100644 --- a/qpdf/qpdf.testcov +++ b/qpdf/qpdf.testcov @@ -596,3 +596,4 @@ QPDFWriter preserve object streams 1 QPDFWriter exclude from object stream 0 check unclosed --pages 1 QPDF_pages findPage not found 0 +qpdf overlay page with no resources 0 diff --git a/qpdf/qtest/qpdf.test b/qpdf/qtest/qpdf.test index 5c58c5a3..fc8c709f 100644 --- a/qpdf/qtest/qpdf.test +++ b/qpdf/qtest/qpdf.test @@ -477,7 +477,7 @@ $td->runtest("compare files", show_ntests(); # ---------- $td->notify("--- Form XObject, underlay, overlay ---"); -$n_tests += 20; +$n_tests += 22; $td->runtest("form xobject creation", {$td->COMMAND => "test_driver 55 fxo-red.pdf"}, @@ -550,6 +550,15 @@ $td->runtest("page operations on form xobject", {$td->FILE => "page-ops-on-form-xobject.out", $td->EXIT_STATUS => 0}, $td->NORMALIZE_NEWLINES); +$td->runtest("overlay on page with no resources", + {$td->COMMAND => + "qpdf --deterministic-id page-with-no-resources.pdf" . + " --overlay minimal.pdf -- a.pdf"}, + {$td->STRING => "", $td->EXIT_STATUS => 0}, + $td->NORMALIZE_NEWLINES); +$td->runtest("check overlay with no resources output", + {$td->FILE => "a.pdf"}, + {$td->FILE => "overlay-no-resources.pdf"}); show_ntests(); # ---------- diff --git a/qpdf/qtest/qpdf/overlay-no-resources.pdf b/qpdf/qtest/qpdf/overlay-no-resources.pdf new file mode 100644 index 00000000..4b41f745 Binary files /dev/null and b/qpdf/qtest/qpdf/overlay-no-resources.pdf differ diff --git a/qpdf/qtest/qpdf/page-with-no-resources.pdf b/qpdf/qtest/qpdf/page-with-no-resources.pdf new file mode 100644 index 00000000..944ea0f0 --- /dev/null +++ b/qpdf/qtest/qpdf/page-with-no-resources.pdf @@ -0,0 +1,21 @@ +%PDF-1.3 +%¿÷¢þ +1 0 obj +<< /Pages 2 0 R /Type /Catalog >> +endobj +2 0 obj +<< /Count 1 /Kids [ 3 0 R ] /Type /Pages >> +endobj +3 0 obj +<< /MediaBox [ 0.0 0.0 612 792 ] /Parent 2 0 R /Type /Page >> +endobj +xref +0 4 +0000000000 65535 f +0000000015 00000 n +0000000064 00000 n +0000000123 00000 n +trailer << /Root 1 0 R /Size 4 /ID [<0c18b42478a35cdccff23c62f4c7b946>] >> +startxref +200 +%%EOF