Commit 315092dd98d5230ef0efa18b294d464d0e9f79d0

Authored by Jay Berkenbilt
1 parent 603f2223

Avoid xref reconstruction infinite loop (fixes #100)

This is CVE-2017-9209.
ChangeLog
1 1 2017-07-26 Jay Berkenbilt <ejb@ql.org>
2 2  
  3 + * CVE-2017-9209: Fix infinite loop caused by attempting to
  4 + reconstruct the xref table while already in the process of
  5 + reconstructing the xref table.
  6 +
3 7 * CVE-2017-9210: Fix infinite loop caused by attempting to unparse
4 8 an object for inclusion in the text of an exception.
5 9  
... ...
include/qpdf/QPDF.hh
... ... @@ -1075,6 +1075,7 @@ class QPDF
1075 1075 // copied_stream_data_provider is owned by copied_streams
1076 1076 CopiedStreamDataProvider* copied_stream_data_provider;
1077 1077 std::set<QPDFObjGen> attachment_streams;
  1078 + bool reconstructed_xref;
1078 1079  
1079 1080 // Linearization data
1080 1081 qpdf_offset_t first_xref_item_offset; // actual value from file
... ...
libqpdf/QPDF.cc
... ... @@ -93,6 +93,7 @@ QPDF::QPDF() :
93 93 cached_key_generation(0),
94 94 pushed_inherited_attributes_to_pages(false),
95 95 copied_stream_data_provider(0),
  96 + reconstructed_xref(false),
96 97 first_xref_item_offset(0),
97 98 uncompressed_after_compressed(false)
98 99 {
... ... @@ -331,6 +332,15 @@ QPDF::setTrailer(QPDFObjectHandle obj)
331 332 void
332 333 QPDF::reconstruct_xref(QPDFExc& e)
333 334 {
  335 + if (this->reconstructed_xref)
  336 + {
  337 + // Avoid xref reconstruction infinite loops
  338 + QTC::TC("qpdf", "QPDF caught recursive xref reconstruction");
  339 + throw e;
  340 + }
  341 +
  342 + this->reconstructed_xref = true;
  343 +
334 344 PCRE obj_re("^\\s*(\\d+)\\s+(\\d+)\\s+obj\\b");
335 345 PCRE endobj_re("^\\s*endobj\\b");
336 346 PCRE trailer_re("^\\s*trailer\\b");
... ...
qpdf/qtest/qpdf.test
... ... @@ -206,7 +206,7 @@ $td-&gt;runtest(&quot;remove page we don&#39;t have&quot;,
206 206 show_ntests();
207 207 # ----------
208 208 $td->notify("--- Miscellaneous Tests ---");
209   -$n_tests += 78;
  209 +$n_tests += 79;
210 210  
211 211 $td->runtest("qpdf version",
212 212 {$td->COMMAND => "qpdf --version"},
... ... @@ -220,6 +220,7 @@ $td-&gt;runtest(&quot;C API: qpdf version&quot;,
220 220  
221 221 # Files to reproduce various bugs
222 222 foreach my $d (
  223 + ["100","xref reconstruction loop"],
223 224 ["101", "resolve for exception text"],
224 225 )
225 226 {
... ...
qpdf/qtest/qpdf/issue-100.out 0 → 100644
  1 +WARNING: issue-100.pdf: file is damaged
  2 +WARNING: issue-100.pdf (file position 736): xref not found
  3 +WARNING: issue-100.pdf: Attempting to reconstruct cross-reference table
  4 +WARNING: issue-100.pdf (object 5 0, file position 489): attempting to recover stream length
  5 +issue-100.pdf (object 6 0, file position 59): expected n n obj
... ...
qpdf/qtest/qpdf/issue-100.pdf 0 → 100644
No preview for this file type