Commit b4d6cf6836ce025ba1811b7bbec52680c7204223
1 parent
f8c8e4dc
Limit depth of nesting in direct objects (fixes #202)
This fixes CVE-2018-9918.
Showing
7 changed files
with
33 additions
and
9 deletions
ChangeLog
libqpdf/QPDFObjectHandle.cc
| ... | ... | @@ -1487,12 +1487,26 @@ QPDFObjectHandle::parseInternal(PointerHolder<InputSource> input, |
| 1487 | 1487 | |
| 1488 | 1488 | case QPDFTokenizer::tt_array_open: |
| 1489 | 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 | 1510 | break; |
| 1497 | 1511 | |
| 1498 | 1512 | case QPDFTokenizer::tt_bool: | ... | ... |
qpdf/qpdf.testcov
qpdf/qtest/qpdf.test
| ... | ... | @@ -236,6 +236,7 @@ my @bug_tests = ( |
| 236 | 236 | ["148", "free memory on bad flate", 2], |
| 237 | 237 | ["149", "xref prev pointer loop", 3], |
| 238 | 238 | ["150", "integer overflow", 2], |
| 239 | + ["202", "even more deeply nested dictionary", 2], | |
| 239 | 240 | ); |
| 240 | 241 | $n_tests += scalar(@bug_tests); |
| 241 | 242 | foreach my $d (@bug_tests) | ... | ... |
qpdf/qtest/qpdf/issue-146.out
| 1 | 1 | WARNING: issue-146.pdf: file is damaged |
| 2 | 2 | WARNING: issue-146.pdf: can't find startxref |
| 3 | 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 | 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