Commit 603f222365252f1a1e20303b3dbe52466be3053b
1 parent
bd6c8456
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.
Showing
5 changed files
with
27 additions
and
3 deletions
ChangeLog
| 1 | +2017-07-26 Jay Berkenbilt <ejb@ql.org> | ||
| 2 | + | ||
| 3 | + * CVE-2017-9210: Fix infinite loop caused by attempting to unparse | ||
| 4 | + an object for inclusion in the text of an exception. | ||
| 5 | + | ||
| 1 | 2015-11-10 Jay Berkenbilt <ejb@ql.org> | 6 | 2015-11-10 Jay Berkenbilt <ejb@ql.org> |
| 2 | 7 | ||
| 3 | * 6.0.0: release | 8 | * 6.0.0: release |
libqpdf/QPDFObjectHandle.cc
| @@ -1076,8 +1076,7 @@ QPDFObjectHandle::parseInternal(PointerHolder<InputSource> input, | @@ -1076,8 +1076,7 @@ QPDFObjectHandle::parseInternal(PointerHolder<InputSource> input, | ||
| 1076 | throw QPDFExc( | 1076 | throw QPDFExc( |
| 1077 | qpdf_e_damaged_pdf, | 1077 | qpdf_e_damaged_pdf, |
| 1078 | input->getName(), object_description, offset, | 1078 | input->getName(), object_description, offset, |
| 1079 | - std::string("dictionary key not name (") + | ||
| 1080 | - key_obj.unparse() + ")"); | 1079 | + std::string("dictionary key is not not a name token")); |
| 1081 | } | 1080 | } |
| 1082 | dict[key_obj.getName()] = val; | 1081 | dict[key_obj.getName()] = val; |
| 1083 | } | 1082 | } |
qpdf/qtest/qpdf.test
| @@ -206,7 +206,7 @@ $td->runtest("remove page we don't have", | @@ -206,7 +206,7 @@ $td->runtest("remove page we don't have", | ||
| 206 | show_ntests(); | 206 | show_ntests(); |
| 207 | # ---------- | 207 | # ---------- |
| 208 | $td->notify("--- Miscellaneous Tests ---"); | 208 | $td->notify("--- Miscellaneous Tests ---"); |
| 209 | -$n_tests += 77; | 209 | +$n_tests += 78; |
| 210 | 210 | ||
| 211 | $td->runtest("qpdf version", | 211 | $td->runtest("qpdf version", |
| 212 | {$td->COMMAND => "qpdf --version"}, | 212 | {$td->COMMAND => "qpdf --version"}, |
| @@ -218,6 +218,20 @@ $td->runtest("C API: qpdf version", | @@ -218,6 +218,20 @@ $td->runtest("C API: qpdf version", | ||
| 218 | $td->EXIT_STATUS => 0}, | 218 | $td->EXIT_STATUS => 0}, |
| 219 | $td->NORMALIZE_NEWLINES); | 219 | $td->NORMALIZE_NEWLINES); |
| 220 | 220 | ||
| 221 | +# Files to reproduce various bugs | ||
| 222 | +foreach my $d ( | ||
| 223 | + ["101", "resolve for exception text"], | ||
| 224 | + ) | ||
| 225 | +{ | ||
| 226 | + my ($n, $description) = @$d; | ||
| 227 | + $td->runtest($description, | ||
| 228 | + {$td->COMMAND => "qpdf issue-$n.pdf a.pdf"}, | ||
| 229 | + {$td->FILE => "issue-$n.out", | ||
| 230 | + $td->EXIT_STATUS => 2}, | ||
| 231 | + $td->NORMALIZE_NEWLINES); | ||
| 232 | +} | ||
| 233 | + | ||
| 234 | + | ||
| 221 | foreach (my $i = 1; $i <= 3; ++$i) | 235 | foreach (my $i = 1; $i <= 3; ++$i) |
| 222 | { | 236 | { |
| 223 | $td->runtest("misc tests", | 237 | $td->runtest("misc tests", |
qpdf/qtest/qpdf/issue-101.out
0 → 100644
| 1 | +WARNING: issue-101.pdf: file is damaged | ||
| 2 | +WARNING: issue-101.pdf (file position 3526): xref not found | ||
| 3 | +WARNING: issue-101.pdf: Attempting to reconstruct cross-reference table | ||
| 4 | +WARNING: issue-101.pdf (object 5 0, file position 1509): attempting to recover stream length | ||
| 5 | +WARNING: issue-101.pdf (object 5 0, file position 2097): attempting to recover stream length | ||
| 6 | +issue-101.pdf (trailer, file position 2928): unknown token while reading object (ÿ) |
qpdf/qtest/qpdf/issue-101.pdf
0 → 100644
No preview for this file type