Commit 4a648b9a00d2c4de37bf17165b20a1fc32956eee

Authored by Jay Berkenbilt
1 parent 9b289336

Fix bug in merging resources /DR from foreign AcroForm (fixes #548)

When making resources indirect in from_dr, the code was using the
wrong owning QPDF, forgetting that from_dr had already been copied
using CopyForeignObject.
ChangeLog
1 1 2021-11-04 Jay Berkenbilt <ejb@ql.org>
2 2  
  3 + * Bug fix: fix crash that could occur under certain conditions
  4 + when using --pages with files that had form fields. Fixes #548.
  5 +
3 6 * Add an extra check to the library to detect when foreign objects
4 7 are inserted directly (instead of using
5 8 <function>QPDF::copyForeignObject</function>) at the time of
... ...
fuzz/build.mk
... ... @@ -41,6 +41,7 @@ CORPUS_FROM_TEST = \
41 41 outlines-with-old-root-dests.pdf \
42 42 page-labels-and-outlines.pdf \
43 43 page-labels-num-tree.pdf \
  44 + dr-with-indirect-item.pdf \
44 45 fuzz-16214.pdf \
45 46 issue-99b.pdf \
46 47 issue-99.pdf \
... ...
fuzz/qtest/fuzz.test
... ... @@ -9,7 +9,7 @@ require TestDriver;
9 9  
10 10 my $td = new TestDriver('fuzz');
11 11  
12   -my $qpdf_n_test_files = 30;
  12 +my $qpdf_n_test_files = 31;
13 13 my @extra = glob("../qpdf_extra/*.fuzz");
14 14 my $qpdf_n_extra_files = scalar(@extra);
15 15 my $qpdf_n_orig_files = 2557;
... ...
libqpdf/QPDFAcroFormDocumentHelper.cc
... ... @@ -1002,8 +1002,10 @@ QPDFAcroFormDocumentHelper::transformAnnotations(
1002 1002 }
1003 1003 // Merge the other document's /DR, creating a conflict
1004 1004 // map. mergeResources checks to make sure both objects
1005   - // are dictionaries.
1006   - from_dr.makeResourcesIndirect(*from_qpdf);
  1005 + // are dictionaries. By this point, if this is foreign,
  1006 + // from_dr has been copied, so we use the target qpdf as
  1007 + // the owning qpdf.
  1008 + from_dr.makeResourcesIndirect(this->qpdf);
1007 1009 dr.mergeResources(from_dr, &dr_map);
1008 1010  
1009 1011 if (from_afdh->getNeedAppearances())
... ...
manual/qpdf-manual.xml
... ... @@ -5086,6 +5086,13 @@ print &quot;\n&quot;;
5086 5086 (with no resource dictionary).
5087 5087 </para>
5088 5088 </listitem>
  5089 + <listitem>
  5090 + <para>
  5091 + Fix crash that could occur under certain conditions when
  5092 + using <option>--pages</option> with files that had form
  5093 + fields.
  5094 + </para>
  5095 + </listitem>
5089 5096 </itemizedlist>
5090 5097 </listitem>
5091 5098 <listitem>
... ...
qpdf/qtest/qpdf.test
... ... @@ -1025,7 +1025,7 @@ my @bug_tests = (
1025 1025 ["335a", "ozz-fuzz-12152", 2],
1026 1026 ["335b", "ozz-fuzz-14845", 2],
1027 1027 ["fuzz-16214", "stream in object stream", 3, "--preserve-unreferenced"],
1028   - # When adding to this list, consider adding to SEED_CORPUS_FILES
  1028 + # When adding to this list, consider adding to CORPUS_FROM_TEST
1029 1029 # in fuzz/build.mk and updating the count in fuzz/qtest/fuzz.test.
1030 1030 );
1031 1031 $n_tests += scalar(@bug_tests);
... ... @@ -3517,7 +3517,7 @@ for (my $n = 16; $n &lt;= 19; ++$n)
3517 3517 show_ntests();
3518 3518 # ----------
3519 3519 $td->notify("--- Specific File Tests ---");
3520   -$n_tests += 9;
  3520 +$n_tests += 11;
3521 3521  
3522 3522 # Special PDF files that caused problems at some point
3523 3523  
... ... @@ -3556,6 +3556,15 @@ $td-&gt;runtest(&quot;pages points to page&quot;,
3556 3556 $td->runtest("check output",
3557 3557 {$td->FILE => "a.pdf"},
3558 3558 {$td->FILE => "pages-is-page-out.pdf"});
  3559 +$td->runtest("Acroform /DR with indirect subkey",
  3560 + {$td->COMMAND =>
  3561 + "qpdf --static-id --empty" .
  3562 + " --pages dr-with-indirect-item.pdf -- a.pdf"},
  3563 + {$td->STRING => "", $td->EXIT_STATUS => 0},
  3564 + $td->NORMALIZE_NEWLINES);
  3565 +$td->runtest("check output",
  3566 + {$td->FILE => "a.pdf"},
  3567 + {$td->FILE => "dr-with-indirect-item-out.pdf"});
3559 3568  
3560 3569 show_ntests();
3561 3570 # ----------
... ...
qpdf/qtest/qpdf/dr-with-indirect-item-out.pdf 0 → 100644
  1 +%PDF-1.3
  2 +%¿÷¢þ
  3 +1 0 obj
  4 +<< /AcroForm 2 0 R /Pages 3 0 R /Type /Catalog >>
  5 +endobj
  6 +2 0 obj
  7 +<< /DR 4 0 R /Fields [ 5 0 R ] >>
  8 +endobj
  9 +3 0 obj
  10 +<< /Count 1 /Kids [ 6 0 R ] /Type /Pages >>
  11 +endobj
  12 +4 0 obj
  13 +<< /Font << /F 7 0 R >> >>
  14 +endobj
  15 +5 0 obj
  16 +<< /DA (0 0 0 rg /Helv 11 Tf) /DV () /F 4 /FT /Tx /P 6 0 R /Rect [ 0 0 1 1 ] /Subtype /Widget /T () /TU () /Type /Annot /V () >>
  17 +endobj
  18 +6 0 obj
  19 +<< /Annots [ 5 0 R ] /MediaBox [ 0 0 1 1 ] /Parent 3 0 R /Resources << /Font << >> >> /Type /Page >>
  20 +endobj
  21 +7 0 obj
  22 +<< >>
  23 +endobj
  24 +xref
  25 +0 8
  26 +0000000000 65535 f
  27 +0000000015 00000 n
  28 +0000000080 00000 n
  29 +0000000129 00000 n
  30 +0000000188 00000 n
  31 +0000000230 00000 n
  32 +0000000374 00000 n
  33 +0000000490 00000 n
  34 +trailer << /Root 1 0 R /Size 8 /ID [<31415926535897932384626433832795><31415926535897932384626433832795>] >>
  35 +startxref
  36 +511
  37 +%%EOF
... ...
qpdf/qtest/qpdf/dr-with-indirect-item.pdf 0 → 100644
  1 +%PDF-1.4
  2 +%¿÷¢þ
  3 +1 0 obj
  4 +<< /AcroForm << /DR 2 0 R /Fields [ 3 0 R ] >> /Pages 4 0 R /Type /Catalog >>
  5 +endobj
  6 +2 0 obj
  7 +<< /Font 5 0 R >>
  8 +endobj
  9 +3 0 obj
  10 +<< /DA (0 0 0 rg /Helv 11 Tf) /DV () /F 4 /FT /Tx /P 6 0 R /Rect [ 0 0 1 1 ] /Subtype /Widget /T () /TU () /Type /Annot /V () >>
  11 +endobj
  12 +4 0 obj
  13 +<< /Count 1 /Kids [ 6 0 R ] /MediaBox [ 0 0 1 1 ] /Resources 2 0 R /Type /Pages >>
  14 +endobj
  15 +5 0 obj
  16 +<< /F << >> >>
  17 +endobj
  18 +6 0 obj
  19 +<< /Annots [ 3 0 R ] /MediaBox [ 0 0 1 1 ] /Parent 4 0 R /Resources 2 0 R /Type /Page >>
  20 +endobj
  21 +xref
  22 +0 7
  23 +0000000000 65535 f
  24 +0000000015 00000 n
  25 +0000000108 00000 n
  26 +0000000141 00000 n
  27 +0000000285 00000 n
  28 +0000000383 00000 n
  29 +0000000413 00000 n
  30 +trailer << /Root 1 0 R /Size 7 /ID [<5e0a553555622a0516e9877ca55217a6><f50ce4731cef7b31118d5f69b0bed95c>] >>
  31 +startxref
  32 +517
  33 +%%EOF
... ...