Commit f60dbb5f2866b297db475f597833e44bf2c5a281

Authored by m-holger
Committed by GitHub
2 parents 4d2a0fe2 d68f45e0

Merge pull request #1476 from m-holger/fuzz

Enhance error handling for unexpected tokens during sanity checks
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
... ...