diff --git a/ChangeLog b/ChangeLog index afe1f628..e21ad6b8 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,9 @@ +2009-10-04 Jay Berkenbilt + + * libqpdf/QPDF.cc (processXRefStream): warn and ignore extra xref + stream entries when stream is larger than reported size. This + used to be a fatal error. (Fixes qpdf-Bugs-2872265.) + 2009-09-27 Jay Berkenbilt * Add several methods to query permissions controlled by the diff --git a/libqpdf/QPDF.cc b/libqpdf/QPDF.cc index 8f275b74..dbbd5517 100644 --- a/libqpdf/QPDF.cc +++ b/libqpdf/QPDF.cc @@ -787,10 +787,18 @@ QPDF::processXRefStream(off_t xref_offset, QPDFObjectHandle& xref_obj) if (expected_size != actual_size) { - throw QPDFExc(this->file.getName(), xref_offset, - "Cross-reference stream data has the wrong size;" - " expected = " + QUtil::int_to_string(expected_size) + - "; actual = " + QUtil::int_to_string(actual_size)); + QPDFExc x(this->file.getName(), xref_offset, + "Cross-reference stream data has the wrong size;" + " expected = " + QUtil::int_to_string(expected_size) + + "; actual = " + QUtil::int_to_string(actual_size)); + if (expected_size > actual_size) + { + throw x; + } + else + { + warn(x); + } } int cur_chunk = 0; diff --git a/qpdf/qtest/qpdf.test b/qpdf/qtest/qpdf.test index 8cf355b0..1c724ec3 100644 --- a/qpdf/qtest/qpdf.test +++ b/qpdf/qtest/qpdf.test @@ -81,7 +81,7 @@ flush_tiff_cache(); show_ntests(); # ---------- $td->notify("--- Miscellaneous Tests ---"); -$n_tests += 4; +$n_tests += 7; foreach (my $i = 1; $i <= 3; ++$i) { @@ -98,6 +98,23 @@ $td->runtest("unknown decode parameters", $td->EXIT_STATUS => 0}, $td->NORMALIZE_NEWLINES); +# Handle xref stream with more entries than reported (bug 2872265) +$td->runtest("xref with short size", + {$td->COMMAND => "qpdf --show-xref xref-with-short-size.pdf"}, + {$td->FILE => "xref-with-short-size.out", + $td->EXIT_STATUS => 3}, + $td->NORMALIZE_NEWLINES); +$td->runtest("recover xref with short size", + {$td->COMMAND => "qpdf xref-with-short-size.pdf a.pdf"}, + {$td->FILE => "xref-with-short-size-recover.out", + $td->EXIT_STATUS => 3}, + $td->NORMALIZE_NEWLINES); +$td->runtest("show new xref stream", + {$td->COMMAND => "qpdf --show-xref a.pdf"}, + {$td->FILE => "xref-with-short-size-new.out", + $td->EXIT_STATUS => 0}, + $td->NORMALIZE_NEWLINES); + show_ntests(); # ---------- $td->notify("--- Error Condition Tests ---"); diff --git a/qpdf/qtest/qpdf/xref-with-short-size-new.out b/qpdf/qtest/qpdf/xref-with-short-size-new.out new file mode 100644 index 00000000..9396e6c6 --- /dev/null +++ b/qpdf/qtest/qpdf/xref-with-short-size-new.out @@ -0,0 +1,13 @@ +1/0: uncompressed; offset = 15 +2/0: compressed; stream = 1, index = 0 +3/0: compressed; stream = 1, index = 1 +4/0: compressed; stream = 1, index = 2 +5/0: compressed; stream = 1, index = 3 +6/0: compressed; stream = 1, index = 4 +7/0: compressed; stream = 1, index = 5 +8/0: compressed; stream = 1, index = 6 +9/0: compressed; stream = 1, index = 7 +10/0: compressed; stream = 1, index = 8 +11/0: uncompressed; offset = 674 +12/0: uncompressed; offset = 801 +13/0: uncompressed; offset = 16194 diff --git a/qpdf/qtest/qpdf/xref-with-short-size-recover.out b/qpdf/qtest/qpdf/xref-with-short-size-recover.out new file mode 100644 index 00000000..52c58986 --- /dev/null +++ b/qpdf/qtest/qpdf/xref-with-short-size-recover.out @@ -0,0 +1,2 @@ +WARNING: xref-with-short-size.pdf: offset 16227: Cross-reference stream data has the wrong size; expected = 52; actual = 56 +qpdf: operation succeeded with warnings; resulting file may have some problems diff --git a/qpdf/qtest/qpdf/xref-with-short-size.out b/qpdf/qtest/qpdf/xref-with-short-size.out new file mode 100644 index 00000000..19f9963e --- /dev/null +++ b/qpdf/qtest/qpdf/xref-with-short-size.out @@ -0,0 +1,14 @@ +WARNING: xref-with-short-size.pdf: offset 16227: Cross-reference stream data has the wrong size; expected = 52; actual = 56 +1/0: compressed; stream = 5, index = 1 +2/0: compressed; stream = 5, index = 0 +3/0: uncompressed; offset = 15 +4/0: compressed; stream = 5, index = 5 +5/0: uncompressed; offset = 15548 +6/0: compressed; stream = 5, index = 6 +7/0: compressed; stream = 5, index = 4 +8/0: compressed; stream = 5, index = 2 +9/0: uncompressed; offset = 150 +10/0: compressed; stream = 5, index = 3 +11/0: compressed; stream = 5, index = 7 +12/0: compressed; stream = 5, index = 8 +qpdf: operation succeeded with warnings; resulting file may have some problems diff --git a/qpdf/qtest/qpdf/xref-with-short-size.pdf b/qpdf/qtest/qpdf/xref-with-short-size.pdf new file mode 100644 index 00000000..3ef4dcdf Binary files /dev/null and b/qpdf/qtest/qpdf/xref-with-short-size.pdf differ