Commit b4d6cf6836ce025ba1811b7bbec52680c7204223

Authored by Jay Berkenbilt
1 parent f8c8e4dc

Limit depth of nesting in direct objects (fixes #202)

This fixes CVE-2018-9918.
ChangeLog
  1 +2018-04-15 Jay Berkenbilt <ejb@ql.org>
  2 +
  3 + * Arbitrarily limit the depth of data structures represented by
  4 + direct object. This is CVE-2018-9918. Fixes #202.
  5 +
1 2018-03-06 Jay Berkenbilt <ejb@ql.org> 6 2018-03-06 Jay Berkenbilt <ejb@ql.org>
2 7
3 * 8.0.2: release 8 * 8.0.2: release
libqpdf/QPDFObjectHandle.cc
@@ -1487,12 +1487,26 @@ QPDFObjectHandle::parseInternal(PointerHolder&lt;InputSource&gt; input, @@ -1487,12 +1487,26 @@ QPDFObjectHandle::parseInternal(PointerHolder&lt;InputSource&gt; input,
1487 1487
1488 case QPDFTokenizer::tt_array_open: 1488 case QPDFTokenizer::tt_array_open:
1489 case QPDFTokenizer::tt_dict_open: 1489 case QPDFTokenizer::tt_dict_open:
1490 - olist_stack.push_back(std::vector<QPDFObjectHandle>());  
1491 - state = st_start;  
1492 - offset_stack.push_back(input->tell());  
1493 - state_stack.push_back(  
1494 - (token.getType() == QPDFTokenizer::tt_array_open) ?  
1495 - st_array : st_dictionary); 1490 + if (olist_stack.size() > 500)
  1491 + {
  1492 + QTC::TC("qpdf", "QPDFObjectHandle too deep");
  1493 + warn(context,
  1494 + QPDFExc(qpdf_e_damaged_pdf, input->getName(),
  1495 + object_description,
  1496 + input->getLastOffset(),
  1497 + "ignoring excessively deeply nested data structure"));
  1498 + object = newNull();
  1499 + state = st_top;
  1500 + }
  1501 + else
  1502 + {
  1503 + olist_stack.push_back(std::vector<QPDFObjectHandle>());
  1504 + state = st_start;
  1505 + offset_stack.push_back(input->tell());
  1506 + state_stack.push_back(
  1507 + (token.getType() == QPDFTokenizer::tt_array_open) ?
  1508 + st_array : st_dictionary);
  1509 + }
1496 break; 1510 break;
1497 1511
1498 case QPDFTokenizer::tt_bool: 1512 case QPDFTokenizer::tt_bool:
qpdf/qpdf.testcov
@@ -335,3 +335,4 @@ QPDFObjectHandle numeric non-numeric 0 @@ -335,3 +335,4 @@ QPDFObjectHandle numeric non-numeric 0
335 QPDFObjectHandle erase array bounds 0 335 QPDFObjectHandle erase array bounds 0
336 qpdf-c called qpdf_check_pdf 0 336 qpdf-c called qpdf_check_pdf 0
337 QPDF xref loop 0 337 QPDF xref loop 0
  338 +QPDFObjectHandle too deep 0
qpdf/qtest/qpdf.test
@@ -236,6 +236,7 @@ my @bug_tests = ( @@ -236,6 +236,7 @@ my @bug_tests = (
236 ["148", "free memory on bad flate", 2], 236 ["148", "free memory on bad flate", 2],
237 ["149", "xref prev pointer loop", 3], 237 ["149", "xref prev pointer loop", 3],
238 ["150", "integer overflow", 2], 238 ["150", "integer overflow", 2],
  239 + ["202", "even more deeply nested dictionary", 2],
239 ); 240 );
240 $n_tests += scalar(@bug_tests); 241 $n_tests += scalar(@bug_tests);
241 foreach my $d (@bug_tests) 242 foreach my $d (@bug_tests)
qpdf/qtest/qpdf/issue-146.out
1 WARNING: issue-146.pdf: file is damaged 1 WARNING: issue-146.pdf: file is damaged
2 WARNING: issue-146.pdf: can't find startxref 2 WARNING: issue-146.pdf: can't find startxref
3 WARNING: issue-146.pdf: Attempting to reconstruct cross-reference table 3 WARNING: issue-146.pdf: Attempting to reconstruct cross-reference table
4 -WARNING: issue-146.pdf (trailer, offset 20728): unknown token while reading object; treating as string  
5 -WARNING: issue-146.pdf (trailer, offset 20732): unexpected EOF  
6 -WARNING: issue-146.pdf (trailer, offset 20732): parse error while reading object 4 +WARNING: issue-146.pdf (trailer, offset 695): ignoring excessively deeply nested data structure
7 issue-146.pdf: unable to find trailer dictionary while recovering damaged file 5 issue-146.pdf: unable to find trailer dictionary while recovering damaged file
qpdf/qtest/qpdf/issue-202.out 0 → 100644
  1 +WARNING: issue-202.pdf (trailer, offset 55770): ignoring excessively deeply nested data structure
  2 +WARNING: issue-202.pdf: file is damaged
  3 +WARNING: issue-202.pdf (offset 54769): expected trailer dictionary
  4 +WARNING: issue-202.pdf: Attempting to reconstruct cross-reference table
  5 +issue-202.pdf: unable to find trailer dictionary while recovering damaged file
qpdf/qtest/qpdf/issue-202.pdf 0 → 100644
No preview for this file type