Skip to content

Commit

Permalink
Browse files Browse the repository at this point in the history
Limit depth of nesting in direct objects (fixes #202)
This fixes CVE-2018-9918.
  • Loading branch information
jberkenbilt committed Apr 15, 2018
1 parent f8c8e4d commit b4d6cf6
Show file tree
Hide file tree
Showing 7 changed files with 33 additions and 9 deletions.
5 changes: 5 additions & 0 deletions ChangeLog
@@ -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>

* 8.0.2: release
Expand Down
26 changes: 20 additions & 6 deletions libqpdf/QPDFObjectHandle.cc
Expand Up @@ -1487,12 +1487,26 @@ QPDFObjectHandle::parseInternal(PointerHolder<InputSource> input,

case QPDFTokenizer::tt_array_open:
case QPDFTokenizer::tt_dict_open:
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);
if (olist_stack.size() > 500)
{
QTC::TC("qpdf", "QPDFObjectHandle too deep");
warn(context,
QPDFExc(qpdf_e_damaged_pdf, input->getName(),
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;

case QPDFTokenizer::tt_bool:
Expand Down
1 change: 1 addition & 0 deletions qpdf/qpdf.testcov
Expand Up @@ -335,3 +335,4 @@ QPDFObjectHandle numeric non-numeric 0
QPDFObjectHandle erase array bounds 0
qpdf-c called qpdf_check_pdf 0
QPDF xref loop 0
QPDFObjectHandle too deep 0
1 change: 1 addition & 0 deletions qpdf/qtest/qpdf.test
Expand Up @@ -236,6 +236,7 @@ my @bug_tests = (
["148", "free memory on bad flate", 2],
["149", "xref prev pointer loop", 3],
["150", "integer overflow", 2],
["202", "even more deeply nested dictionary", 2],
);
$n_tests += scalar(@bug_tests);
foreach my $d (@bug_tests)
Expand Down
4 changes: 1 addition & 3 deletions qpdf/qtest/qpdf/issue-146.out
@@ -1,7 +1,5 @@
WARNING: issue-146.pdf: file is damaged
WARNING: issue-146.pdf: can't find startxref
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 20732): unexpected EOF
WARNING: issue-146.pdf (trailer, offset 20732): parse error while reading object
WARNING: issue-146.pdf (trailer, offset 695): ignoring excessively deeply nested data structure
issue-146.pdf: unable to find trailer dictionary while recovering damaged file
5 changes: 5 additions & 0 deletions qpdf/qtest/qpdf/issue-202.out
@@ -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 added qpdf/qtest/qpdf/issue-202.pdf
Binary file not shown.

0 comments on commit b4d6cf6

Please sign in to comment.