From 603f222365252f1a1e20303b3dbe52466be3053b Mon Sep 17 00:00:00 2001 From: Jay Berkenbilt Date: Tue, 25 Jul 2017 10:13:30 -0400 Subject: Fix infinite loop while reporting an error (fixes #101) This is CVE-2017-9210. The description string for an error message included unparsing an object, which is too complex of a thing to try to do while throwing an exception. There was only one example of this in the entire codebase, so it is not a pervasive problem. Fixing this eliminated one class of infinite loop errors. --- ChangeLog | 5 +++++ libqpdf/QPDFObjectHandle.cc | 3 +-- qpdf/qtest/qpdf.test | 16 +++++++++++++++- qpdf/qtest/qpdf/issue-101.out | 6 ++++++ qpdf/qtest/qpdf/issue-101.pdf | Bin 0 -> 4613 bytes 5 files changed, 27 insertions(+), 3 deletions(-) create mode 100644 qpdf/qtest/qpdf/issue-101.out create mode 100644 qpdf/qtest/qpdf/issue-101.pdf diff --git a/ChangeLog b/ChangeLog index 548106ee..32bafad6 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,8 @@ +2017-07-26 Jay Berkenbilt + + * CVE-2017-9210: Fix infinite loop caused by attempting to unparse + an object for inclusion in the text of an exception. + 2015-11-10 Jay Berkenbilt * 6.0.0: release diff --git a/libqpdf/QPDFObjectHandle.cc b/libqpdf/QPDFObjectHandle.cc index 64a4e3c3..687ba439 100644 --- a/libqpdf/QPDFObjectHandle.cc +++ b/libqpdf/QPDFObjectHandle.cc @@ -1076,8 +1076,7 @@ QPDFObjectHandle::parseInternal(PointerHolder input, throw QPDFExc( qpdf_e_damaged_pdf, input->getName(), object_description, offset, - std::string("dictionary key not name (") + - key_obj.unparse() + ")"); + std::string("dictionary key is not not a name token")); } dict[key_obj.getName()] = val; } diff --git a/qpdf/qtest/qpdf.test b/qpdf/qtest/qpdf.test index c17271d9..e0b2609a 100644 --- a/qpdf/qtest/qpdf.test +++ b/qpdf/qtest/qpdf.test @@ -206,7 +206,7 @@ $td->runtest("remove page we don't have", show_ntests(); # ---------- $td->notify("--- Miscellaneous Tests ---"); -$n_tests += 77; +$n_tests += 78; $td->runtest("qpdf version", {$td->COMMAND => "qpdf --version"}, @@ -218,6 +218,20 @@ $td->runtest("C API: qpdf version", $td->EXIT_STATUS => 0}, $td->NORMALIZE_NEWLINES); +# Files to reproduce various bugs +foreach my $d ( + ["101", "resolve for exception text"], + ) +{ + my ($n, $description) = @$d; + $td->runtest($description, + {$td->COMMAND => "qpdf issue-$n.pdf a.pdf"}, + {$td->FILE => "issue-$n.out", + $td->EXIT_STATUS => 2}, + $td->NORMALIZE_NEWLINES); +} + + foreach (my $i = 1; $i <= 3; ++$i) { $td->runtest("misc tests", diff --git a/qpdf/qtest/qpdf/issue-101.out b/qpdf/qtest/qpdf/issue-101.out new file mode 100644 index 00000000..59bd8103 --- /dev/null +++ b/qpdf/qtest/qpdf/issue-101.out @@ -0,0 +1,6 @@ +WARNING: issue-101.pdf: file is damaged +WARNING: issue-101.pdf (file position 3526): xref not found +WARNING: issue-101.pdf: Attempting to reconstruct cross-reference table +WARNING: issue-101.pdf (object 5 0, file position 1509): attempting to recover stream length +WARNING: issue-101.pdf (object 5 0, file position 2097): attempting to recover stream length +issue-101.pdf (trailer, file position 2928): unknown token while reading object (ÿ) diff --git a/qpdf/qtest/qpdf/issue-101.pdf b/qpdf/qtest/qpdf/issue-101.pdf new file mode 100644 index 00000000..801b7c3a Binary files /dev/null and b/qpdf/qtest/qpdf/issue-101.pdf differ -- cgit v1.2.3-54-g00ecf