Commit f60dbb5f2866b297db475f597833e44bf2c5a281
Committed by
GitHub
Merge pull request #1476 from m-holger/fuzz
Enhance error handling for unexpected tokens during sanity checks
Showing
4 changed files
with
44 additions
and
43 deletions
libqpdf/QPDFParser.cc
| ... | ... | @@ -324,6 +324,12 @@ QPDFParser::parseRemainder(bool content_stream) |
| 324 | 324 | add(std::move(object)); |
| 325 | 325 | } else { |
| 326 | 326 | QTC::TC("qpdf", "QPDFParser bad array close in parseRemainder"); |
| 327 | + if (sanity_checks) { | |
| 328 | + // During sanity checks, assume nesting of containers is corrupt and object is | |
| 329 | + // unusable. | |
| 330 | + warn("unexpected array close token; giving up on reading object"); | |
| 331 | + return {QPDFObject::create<QPDF_Null>()}; | |
| 332 | + } | |
| 327 | 333 | warn("treating unexpected array close token as null"); |
| 328 | 334 | if (tooManyBadTokens()) { |
| 329 | 335 | return {QPDFObject::create<QPDF_Null>()}; |
| ... | ... | @@ -374,6 +380,12 @@ QPDFParser::parseRemainder(bool content_stream) |
| 374 | 380 | add(std::move(object)); |
| 375 | 381 | } else { |
| 376 | 382 | QTC::TC("qpdf", "QPDFParser bad dictionary close in parseRemainder"); |
| 383 | + if (sanity_checks) { | |
| 384 | + // During sanity checks, assume nesting of containers is corrupt and object is | |
| 385 | + // unusable. | |
| 386 | + warn("unexpected dictionary close token; giving up on reading object"); | |
| 387 | + return {QPDFObject::create<QPDF_Null>()}; | |
| 388 | + } | |
| 377 | 389 | warn("unexpected dictionary close token"); |
| 378 | 390 | if (tooManyBadTokens()) { |
| 379 | 391 | return {QPDFObject::create<QPDF_Null>()}; |
| ... | ... | @@ -436,6 +448,15 @@ QPDFParser::parseRemainder(bool content_stream) |
| 436 | 448 | if (content_stream) { |
| 437 | 449 | addScalar<QPDF_Operator>(tokenizer.getValue()); |
| 438 | 450 | } else { |
| 451 | + if (sanity_checks && | |
| 452 | + (tokenizer.getValue() == "endobj" || tokenizer.getValue() == "endstream")) { | |
| 453 | + // During sanity checks, assume an unexpected endobj or endstream indicates that | |
| 454 | + // we are parsing past the end of the object. | |
| 455 | + warn( | |
| 456 | + "unexpected 'endobj' or 'endstream' while reading object; giving up on " | |
| 457 | + "reading object"); | |
| 458 | + return {QPDFObject::create<QPDF_Null>()}; | |
| 459 | + } | |
| 439 | 460 | QTC::TC("qpdf", "QPDFParser treat word as string in parseRemainder"); |
| 440 | 461 | warn("unknown token while reading object; treating as string"); |
| 441 | 462 | if (tooManyBadTokens()) { | ... | ... |
qpdf/qtest/qpdf/bad16-recover.out
| ... | ... | @@ -6,11 +6,7 @@ WARNING: bad16.pdf (trailer, offset 779): unexpected EOF |
| 6 | 6 | WARNING: bad16.pdf: file is damaged |
| 7 | 7 | WARNING: bad16.pdf (offset 712): expected trailer dictionary |
| 8 | 8 | WARNING: bad16.pdf: Attempting to reconstruct cross-reference table |
| 9 | -WARNING: bad16.pdf (trailer, offset 753): unexpected dictionary close token | |
| 10 | -WARNING: bad16.pdf (trailer, offset 756): unexpected dictionary close token | |
| 11 | -WARNING: bad16.pdf (trailer, offset 759): unknown token while reading object; treating as string | |
| 12 | -WARNING: bad16.pdf (trailer, offset 779): parse error while reading object | |
| 13 | -WARNING: bad16.pdf (trailer, offset 779): unexpected EOF | |
| 9 | +WARNING: bad16.pdf (trailer, offset 753): unexpected dictionary close token; giving up on reading object | |
| 14 | 10 | WARNING: bad16.pdf: unable to find trailer dictionary while recovering damaged file |
| 15 | 11 | /QTest is implicit |
| 16 | 12 | /QTest is direct and has type null (2) | ... | ... |
qpdf/qtest/qpdf/issue-335a.out
| ... | ... | @@ -144,28 +144,10 @@ WARNING: issue-335a.pdf (trailer, offset 21452): invalid character (-) in hexstr |
| 144 | 144 | WARNING: issue-335a.pdf (trailer, offset 21436): stream keyword found in trailer |
| 145 | 145 | WARNING: issue-335a.pdf (trailer, offset 21407): recovered trailer has no /Root entry |
| 146 | 146 | WARNING: issue-335a.pdf (trailer, offset 21287): unknown token while reading object; treating as string |
| 147 | -WARNING: issue-335a.pdf (trailer, offset 21389): unexpected dictionary close token | |
| 148 | -WARNING: issue-335a.pdf (trailer, offset 21392): unknown token while reading object; treating as string | |
| 149 | -WARNING: issue-335a.pdf (trailer, offset 21400): unknown token while reading object; treating as string | |
| 150 | -WARNING: issue-335a.pdf (trailer, offset 21430): unknown token while reading object; treating as string | |
| 151 | -WARNING: issue-335a.pdf (trailer, offset 21438): unknown token while reading object; treating as string | |
| 152 | -WARNING: issue-335a.pdf (trailer, offset 21441): unknown token while reading object; treating as string | |
| 153 | -WARNING: issue-335a.pdf (trailer, offset 21444): unknown token while reading object; treating as string | |
| 154 | -WARNING: issue-335a.pdf (trailer, offset 21452): invalid character (-) in hexstring | |
| 155 | -WARNING: issue-335a.pdf (trailer, offset 21819): unknown token while reading object; treating as string | |
| 156 | -WARNING: issue-335a.pdf (trailer, offset 21819): too many errors; giving up on reading object | |
| 147 | +WARNING: issue-335a.pdf (trailer, offset 21389): unexpected dictionary close token; giving up on reading object | |
| 157 | 148 | WARNING: issue-335a.pdf (trailer, offset 21277): unknown token while reading object; treating as string |
| 158 | 149 | WARNING: issue-335a.pdf (trailer, offset 21287): unknown token while reading object; treating as string |
| 159 | -WARNING: issue-335a.pdf (trailer, offset 21389): unexpected dictionary close token | |
| 160 | -WARNING: issue-335a.pdf (trailer, offset 21392): unknown token while reading object; treating as string | |
| 161 | -WARNING: issue-335a.pdf (trailer, offset 21400): unknown token while reading object; treating as string | |
| 162 | -WARNING: issue-335a.pdf (trailer, offset 21430): unknown token while reading object; treating as string | |
| 163 | -WARNING: issue-335a.pdf (trailer, offset 21438): unknown token while reading object; treating as string | |
| 164 | -WARNING: issue-335a.pdf (trailer, offset 21441): unknown token while reading object; treating as string | |
| 165 | -WARNING: issue-335a.pdf (trailer, offset 21444): unknown token while reading object; treating as string | |
| 166 | -WARNING: issue-335a.pdf (trailer, offset 21452): invalid character (-) in hexstring | |
| 167 | -WARNING: issue-335a.pdf (trailer, offset 21819): unknown token while reading object; treating as string | |
| 168 | -WARNING: issue-335a.pdf (trailer, offset 21819): too many errors; giving up on reading object | |
| 150 | +WARNING: issue-335a.pdf (trailer, offset 21389): unexpected dictionary close token; giving up on reading object | |
| 169 | 151 | WARNING: issue-335a.pdf (trailer, offset 21228): treating unexpected brace token as null |
| 170 | 152 | WARNING: issue-335a.pdf (trailer, offset 21229): unexpected ) |
| 171 | 153 | WARNING: issue-335a.pdf (trailer, offset 21230): unknown token while reading object; treating as string |
| ... | ... | @@ -1003,4 +985,20 @@ WARNING: issue-335a.pdf (trailer, offset 499): unexpected ) |
| 1003 | 985 | WARNING: issue-335a.pdf (trailer, offset 563): unexpected ) |
| 1004 | 986 | WARNING: issue-335a.pdf (trailer, offset 596): unexpected ) |
| 1005 | 987 | WARNING: issue-335a.pdf (trailer, offset 596): too many errors; giving up on reading object |
| 988 | +WARNING: issue-335a.pdf (trailer, offset 461): invalid character (<) in hexstring | |
| 989 | +WARNING: issue-335a.pdf (trailer, offset 447): unknown token while reading object; treating as string | |
| 990 | +WARNING: issue-335a.pdf (trailer, offset 450): unknown token while reading object; treating as string | |
| 991 | +WARNING: issue-335a.pdf (trailer, offset 461): invalid character (<) in hexstring | |
| 992 | +WARNING: issue-335a.pdf (trailer, offset 464): invalid character (¨) in hexstring | |
| 993 | +WARNING: issue-335a.pdf (trailer, offset 499): unexpected ) | |
| 994 | +WARNING: issue-335a.pdf (trailer, offset 563): unexpected ) | |
| 995 | +WARNING: issue-335a.pdf (trailer, offset 563): too many errors; giving up on reading object | |
| 996 | +WARNING: issue-335a.pdf (trailer, offset 431): treating unexpected brace token as null | |
| 997 | +WARNING: issue-335a.pdf (trailer, offset 432): unexpected ) | |
| 998 | +WARNING: issue-335a.pdf (trailer, offset 433): unexpected ) | |
| 999 | +WARNING: issue-335a.pdf (trailer, offset 563): unexpected ) | |
| 1000 | +WARNING: issue-335a.pdf (trailer, offset 596): unexpected ) | |
| 1001 | +WARNING: issue-335a.pdf (trailer, offset 597): name with stray # will not work with PDF >= 1.2 | |
| 1002 | +WARNING: issue-335a.pdf (trailer, offset 600): unexpected ) | |
| 1003 | +WARNING: issue-335a.pdf (trailer, offset 600): too many errors; giving up on reading object | |
| 1006 | 1004 | qpdf: issue-335a.pdf: too many errors while reconstructing cross-reference table | ... | ... |
qpdf/qtest/qpdf/issue-99.out
| ... | ... | @@ -11,28 +11,14 @@ WARNING: issue-99.pdf (object 1 0, offset 855): too many errors; giving up on re |
| 11 | 11 | WARNING: issue-99.pdf (object 1 0, offset 858): expected endobj |
| 12 | 12 | WARNING: issue-99.pdf (object 2 0, offset 64): expected endobj |
| 13 | 13 | WARNING: issue-99.pdf (object 5 0, offset 2452): unknown token while reading object; treating as string |
| 14 | -WARNING: issue-99.pdf (object 6 0, offset 2506): treating unexpected array close token as null | |
| 15 | -WARNING: issue-99.pdf (object 6 0, offset 2507): unknown token while reading object; treating as string | |
| 16 | -WARNING: issue-99.pdf (object 6 0, offset 2551): unknown token while reading object; treating as string | |
| 17 | -WARNING: issue-99.pdf (object 6 0, offset 2475): dictionary has duplicated key /Type; last occurrence overrides earlier ones | |
| 18 | -WARNING: issue-99.pdf (object 6 0, offset 2475): dictionary has duplicated key /Parent; last occurrence overrides earlier ones | |
| 19 | -WARNING: issue-99.pdf (object 6 0, offset 2475): dictionary has duplicated key /Group; last occurrence overrides earlier ones | |
| 20 | -WARNING: issue-99.pdf (object 6 0, offset 2475): expected dictionary key but found non-name object; inserting key /QPDFFake1 | |
| 21 | -WARNING: issue-99.pdf (object 6 0, offset 2475): expected dictionary key but found non-name object; inserting key /QPDFFake2 | |
| 22 | -WARNING: issue-99.pdf (object 6 0, offset 2475): expected dictionary key but found non-name object; inserting key /QPDFFake3 | |
| 14 | +WARNING: issue-99.pdf (object 6 0, offset 2506): unexpected array close token; giving up on reading object | |
| 15 | +WARNING: issue-99.pdf (object 6 0, offset 2507): expected endobj | |
| 23 | 16 | WARNING: issue-99.pdf (object 10 0, offset 3708): expected dictionary key but found non-name object; inserting key /QPDFFake1 |
| 24 | 17 | WARNING: issue-99.pdf (object 11 0, offset 4485): unknown token while reading object; treating as string |
| 25 | -WARNING: issue-99.pdf (object 11 0, offset 4497): treating unexpected array close token as null | |
| 26 | -WARNING: issue-99.pdf (object 11 0, offset 4502): unexpected ) | |
| 27 | -WARNING: issue-99.pdf (object 11 0, offset 4504): unexpected > | |
| 28 | -WARNING: issue-99.pdf (object 11 0, offset 4508): unknown token while reading object; treating as string | |
| 29 | -WARNING: issue-99.pdf (object 11 0, offset 4520): unknown token while reading object; treating as string | |
| 30 | -WARNING: issue-99.pdf (object 11 0, offset 4520): too many errors; giving up on reading object | |
| 31 | -WARNING: issue-99.pdf (object 11 0, offset 4524): expected endobj | |
| 18 | +WARNING: issue-99.pdf (object 11 0, offset 4497): unexpected array close token; giving up on reading object | |
| 19 | +WARNING: issue-99.pdf (object 11 0, offset 4499): expected endobj | |
| 32 | 20 | WARNING: issue-99.pdf: unable to find trailer dictionary while recovering damaged file |
| 33 | 21 | WARNING: object 1 0: Pages tree includes non-dictionary object; ignoring |
| 34 | 22 | WARNING: object 1 0: operation for dictionary attempted on object of type null: returning false for a key containment request |
| 35 | 23 | WARNING: object 1 0: operation for dictionary attempted on object of type null: ignoring key replacement request |
| 36 | -WARNING: object 1 0: operation for dictionary attempted on object of type null: returning false for a key containment request | |
| 37 | -WARNING: object 1 0: operation for dictionary attempted on object of type null: ignoring key replacement request | |
| 38 | 24 | qpdf: issue-99.pdf: unable to find any pages while recovering damaged file | ... | ... |