Commit 54ac92eb1de607fba7fb5d7a8aaa2fbcf80deeb0
Committed by
GitHub
Merge pull request #1271 from m-holger/rsl
Fix QPDF::recoverStreamLength
Showing
9 changed files
with
121 additions
and
17 deletions
.idea/codeStyles/Project.xml
| ... | ... | @@ -3,7 +3,7 @@ |
| 3 | 3 | <RiderCodeStyleSettings> |
| 4 | 4 | <option name="/Default/CodeStyle/CodeFormatting/CppClangFormat/EnableClangFormatSupport/@EntryValue" value="true" type="bool" /> |
| 5 | 5 | </RiderCodeStyleSettings> |
| 6 | - <SqlCodeStyleSettings version="7"> | |
| 6 | + <SqlCodeStyleSettings version="6"> | |
| 7 | 7 | <option name="KEYWORD_CASE" value="2" /> |
| 8 | 8 | </SqlCodeStyleSettings> |
| 9 | 9 | <clangFormatSettings> | ... | ... |
libqpdf/QPDF.cc
| ... | ... | @@ -1649,26 +1649,28 @@ QPDF::recoverStreamLength( |
| 1649 | 1649 | } |
| 1650 | 1650 | |
| 1651 | 1651 | if (length) { |
| 1652 | - qpdf_offset_t this_obj_offset = 0; | |
| 1653 | - QPDFObjGen this_og; | |
| 1652 | + auto end = stream_offset + toO(length); | |
| 1653 | + qpdf_offset_t found_offset = 0; | |
| 1654 | + QPDFObjGen found_og; | |
| 1654 | 1655 | |
| 1655 | 1656 | // Make sure this is inside this object |
| 1656 | - for (auto const& iter: m->xref_table) { | |
| 1657 | - QPDFXRefEntry const& entry = iter.second; | |
| 1657 | + for (auto const& [current_og, entry]: m->xref_table) { | |
| 1658 | 1658 | if (entry.getType() == 1) { |
| 1659 | 1659 | qpdf_offset_t obj_offset = entry.getOffset(); |
| 1660 | - if ((obj_offset > stream_offset) && | |
| 1661 | - ((this_obj_offset == 0) || (this_obj_offset > obj_offset))) { | |
| 1662 | - this_obj_offset = obj_offset; | |
| 1663 | - this_og = iter.first; | |
| 1660 | + if (found_offset < obj_offset && obj_offset < end) { | |
| 1661 | + found_offset = obj_offset; | |
| 1662 | + found_og = current_og; | |
| 1664 | 1663 | } |
| 1665 | 1664 | } |
| 1666 | 1665 | } |
| 1667 | - if (this_obj_offset && (this_og == og)) { | |
| 1668 | - // Well, we found endstream\nendobj within the space allowed for this object, so we're | |
| 1669 | - // probably in good shape. | |
| 1666 | + if (!found_offset || found_og == og) { | |
| 1667 | + // If we are trying to recover an XRef stream the xref table will not contain and | |
| 1668 | + // won't contain any entries, therefore we cannot check the found length. Otherwise we | |
| 1669 | + // found endstream\nendobj within the space allowed for this object, so we're probably | |
| 1670 | + // in good shape. | |
| 1670 | 1671 | } else { |
| 1671 | 1672 | QTC::TC("qpdf", "QPDF found wrong endstream in recovery"); |
| 1673 | + length = 0; | |
| 1672 | 1674 | } |
| 1673 | 1675 | } |
| 1674 | 1676 | ... | ... |
qpdf/qtest/error-condition.test
| ... | ... | @@ -55,6 +55,7 @@ my @badfiles = ("not a PDF file", # 1 |
| 55 | 55 | "bad dictionary key", # 36 |
| 56 | 56 | "space before xref", # 37 |
| 57 | 57 | "startxref to space then eof", # 38 |
| 58 | + "stream lenth revocery overlapping", # 39 | |
| 58 | 59 | ); |
| 59 | 60 | |
| 60 | 61 | $n_tests += @badfiles + 8; |
| ... | ... | @@ -65,7 +66,7 @@ $n_tests += @badfiles + 8; |
| 65 | 66 | # have error conditions that used to be fatal but are now considered |
| 66 | 67 | # non-fatal. |
| 67 | 68 | my %badtest_overrides = (); |
| 68 | -for(6, 12..15, 17, 18..32, 34..37) | |
| 69 | +for(6, 12..15, 17, 18..32, 34..37, 39) | |
| 69 | 70 | { |
| 70 | 71 | $badtest_overrides{$_} = 0; |
| 71 | 72 | } | ... | ... |
qpdf/qtest/parsing.test
| ... | ... | @@ -17,7 +17,7 @@ my $td = new TestDriver('parsing'); |
| 17 | 17 | my $n_tests = 17; |
| 18 | 18 | |
| 19 | 19 | $td->runtest("parse objects from string", |
| 20 | - {$td->COMMAND => "test_driver 31 bad39.qdf"}, | |
| 20 | + {$td->COMMAND => "test_driver 31 bad-parse.qdf"}, | |
| 21 | 21 | {$td->FILE => "parse-object.out", $td->EXIT_STATUS => 0}, |
| 22 | 22 | $td->NORMALIZE_NEWLINES); |
| 23 | 23 | $td->runtest("EOF terminating literal tokens", | ... | ... |
qpdf/qtest/qpdf/bad39.qdf renamed to qpdf/qtest/qpdf/bad-parse.qdf
qpdf/qtest/qpdf/bad39-recover.out
0 โ 100644
| 1 | +WARNING: bad39.pdf (object 4 0, offset 385): expected endstream | |
| 2 | +WARNING: bad39.pdf (object 4 0, offset 341): attempting to recover stream length | |
| 3 | +WARNING: bad39.pdf (object 4 0, offset 341): unable to recover stream data; treating stream as empty | |
| 4 | +/QTest is indirect and has type stream (10) | |
| 5 | +/QTest is a stream. Dictionary: << /Length 44 >> | |
| 6 | +Raw stream data: | |
| 7 | + | |
| 8 | +Uncompressed stream data: | |
| 9 | + | |
| 10 | +End of stream data | |
| 11 | +unparse: 4 0 R | |
| 12 | +unparseResolved: 4 0 R | |
| 13 | +test 1 done | ... | ... |
qpdf/qtest/qpdf/bad39.out
0 โ 100644
qpdf/qtest/qpdf/bad39.pdf
0 โ 100644
| 1 | +%PDF-1.3 | |
| 2 | +1 0 obj | |
| 3 | +<< | |
| 4 | + /Type /Catalog | |
| 5 | + /Pages 2 0 R | |
| 6 | +>> | |
| 7 | +endobj | |
| 8 | + | |
| 9 | +2 0 obj | |
| 10 | +<< | |
| 11 | + /Type /Pages | |
| 12 | + /Kids [ | |
| 13 | + 3 0 R | |
| 14 | + ] | |
| 15 | + /Count 1 | |
| 16 | +>> | |
| 17 | +endobj | |
| 18 | + | |
| 19 | +3 0 obj | |
| 20 | +<< | |
| 21 | + /Type /Page | |
| 22 | + /Parent 2 0 R | |
| 23 | + /MediaBox [0 0 612 792] | |
| 24 | + /Contents 4 0 R | |
| 25 | + /Resources << | |
| 26 | + /ProcSet 5 0 R | |
| 27 | + /Font << | |
| 28 | + /F1 6 0 R | |
| 29 | + >> | |
| 30 | + >> | |
| 31 | +>> | |
| 32 | +endobj | |
| 33 | + | |
| 34 | +4 0 obj | |
| 35 | +<< | |
| 36 | + /Length 44 | |
| 37 | +>> | |
| 38 | +stream | |
| 39 | +BT | |
| 40 | + /F1 24 Tf | |
| 41 | + 72 720 Td | |
| 42 | + (Potato) Tj | |
| 43 | +ET | |
| 44 | +enxstream | |
| 45 | +enxobj | |
| 46 | + | |
| 47 | +5 0 obj | |
| 48 | +[ | |
| 49 | ||
| 50 | + /Text | |
| 51 | +] | |
| 52 | +endobj | |
| 53 | + | |
| 54 | +6 0 obj | |
| 55 | +<< | |
| 56 | + /Type /Font | |
| 57 | + /Subtype /Type1 | |
| 58 | + /Name /F1 | |
| 59 | + /BaseFont /Helvetica | |
| 60 | + /Encoding /Winng | |
| 61 | +>> | |
| 62 | +endstream | |
| 63 | +endobj | |
| 64 | + | |
| 65 | +xref | |
| 66 | +0 7 | |
| 67 | +0000000000 65535 f | |
| 68 | +0000000009 00000 n | |
| 69 | +0000000063 00000 n | |
| 70 | +0000000135 00000 n | |
| 71 | +0000000307 00000 n | |
| 72 | +0000000403 00000 n | |
| 73 | +0000000438 00000 n | |
| 74 | +trailer << | |
| 75 | + /Size 7 | |
| 76 | + /Root 1 0 R | |
| 77 | + /QTest 4 0 R | |
| 78 | +>> | |
| 79 | +startxref | |
| 80 | +556 | |
| 81 | +%%EOF | ... | ... |
qpdf/qtest/qpdf/parse-object.out
| ... | ... | @@ -5,7 +5,7 @@ WARNING: parsed object (offset 9): unknown token while reading object; treating |
| 5 | 5 | WARNING: parsed object: treating unexpected brace token as null |
| 6 | 6 | WARNING: parsed object: treating unexpected brace token as null |
| 7 | 7 | WARNING: parsed object: unexpected dictionary close token |
| 8 | -WARNING: bad39.qdf (object 7 0, offset 1121): unexpected EOF | |
| 9 | -WARNING: bad39.qdf (object 7 0, offset 1121): expected endobj | |
| 10 | -WARNING: bad39.qdf (object 7 0, offset 1121): EOF after endobj | |
| 8 | +WARNING: bad-parse.qdf (object 7 0, offset 1121): unexpected EOF | |
| 9 | +WARNING: bad-parse.qdf (object 7 0, offset 1121): expected endobj | |
| 10 | +WARNING: bad-parse.qdf (object 7 0, offset 1121): EOF after endobj | |
| 11 | 11 | test 31 done | ... | ... |