2
1
mirror of https://github.com/qpdf/qpdf.git synced 2024-06-05 11:50:53 +00:00

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

This fixes CVE-2018-9918.
This commit is contained in:
Jay Berkenbilt 2018-04-15 16:11:22 -04:00
parent f8c8e4dcc0
commit b4d6cf6836
7 changed files with 33 additions and 9 deletions

View File

@ -1,3 +1,8 @@
2018-04-15 Jay Berkenbilt <ejb@ql.org>
* Arbitrarily limit the depth of data structures represented by
direct object. This is CVE-2018-9918. Fixes #202.
2018-03-06 Jay Berkenbilt <ejb@ql.org> 2018-03-06 Jay Berkenbilt <ejb@ql.org>
* 8.0.2: release * 8.0.2: release

View File

@ -1487,12 +1487,26 @@ QPDFObjectHandle::parseInternal(PointerHolder<InputSource> input,
case QPDFTokenizer::tt_array_open: case QPDFTokenizer::tt_array_open:
case QPDFTokenizer::tt_dict_open: case QPDFTokenizer::tt_dict_open:
olist_stack.push_back(std::vector<QPDFObjectHandle>()); if (olist_stack.size() > 500)
state = st_start; {
offset_stack.push_back(input->tell()); QTC::TC("qpdf", "QPDFObjectHandle too deep");
state_stack.push_back( warn(context,
(token.getType() == QPDFTokenizer::tt_array_open) ? QPDFExc(qpdf_e_damaged_pdf, input->getName(),
st_array : st_dictionary); object_description,
input->getLastOffset(),
"ignoring excessively deeply nested data structure"));
object = newNull();
state = st_top;
}
else
{
olist_stack.push_back(std::vector<QPDFObjectHandle>());
state = st_start;
offset_stack.push_back(input->tell());
state_stack.push_back(
(token.getType() == QPDFTokenizer::tt_array_open) ?
st_array : st_dictionary);
}
break; break;
case QPDFTokenizer::tt_bool: case QPDFTokenizer::tt_bool:

View File

@ -335,3 +335,4 @@ QPDFObjectHandle numeric non-numeric 0
QPDFObjectHandle erase array bounds 0 QPDFObjectHandle erase array bounds 0
qpdf-c called qpdf_check_pdf 0 qpdf-c called qpdf_check_pdf 0
QPDF xref loop 0 QPDF xref loop 0
QPDFObjectHandle too deep 0

View File

@ -236,6 +236,7 @@ my @bug_tests = (
["148", "free memory on bad flate", 2], ["148", "free memory on bad flate", 2],
["149", "xref prev pointer loop", 3], ["149", "xref prev pointer loop", 3],
["150", "integer overflow", 2], ["150", "integer overflow", 2],
["202", "even more deeply nested dictionary", 2],
); );
$n_tests += scalar(@bug_tests); $n_tests += scalar(@bug_tests);
foreach my $d (@bug_tests) foreach my $d (@bug_tests)

View File

@ -1,7 +1,5 @@
WARNING: issue-146.pdf: file is damaged WARNING: issue-146.pdf: file is damaged
WARNING: issue-146.pdf: can't find startxref WARNING: issue-146.pdf: can't find startxref
WARNING: issue-146.pdf: Attempting to reconstruct cross-reference table WARNING: issue-146.pdf: Attempting to reconstruct cross-reference table
WARNING: issue-146.pdf (trailer, offset 20728): unknown token while reading object; treating as string WARNING: issue-146.pdf (trailer, offset 695): ignoring excessively deeply nested data structure
WARNING: issue-146.pdf (trailer, offset 20732): unexpected EOF
WARNING: issue-146.pdf (trailer, offset 20732): parse error while reading object
issue-146.pdf: unable to find trailer dictionary while recovering damaged file issue-146.pdf: unable to find trailer dictionary while recovering damaged file

View File

@ -0,0 +1,5 @@
WARNING: issue-202.pdf (trailer, offset 55770): ignoring excessively deeply nested data structure
WARNING: issue-202.pdf: file is damaged
WARNING: issue-202.pdf (offset 54769): expected trailer dictionary
WARNING: issue-202.pdf: Attempting to reconstruct cross-reference table
issue-202.pdf: unable to find trailer dictionary while recovering damaged file

Binary file not shown.