Commit 3eb4b066ab3f25f6454214d33b2fc17161812dfa

Authored by Jay Berkenbilt
1 parent b097d7a8

Security: better bounds checks for linearization data

The faulty code was only used during explicit checks of linearization
data.  Those checks are not part of normal reading or writing of PDF
files.
ChangeLog
1 2013-10-05 Jay Berkenbilt <ejb@ql.org> 1 2013-10-05 Jay Berkenbilt <ejb@ql.org>
2 2
  3 + * Security fix: avoid buffer overrun that could be caused by bogus
  4 + data in linearization hint streams. The incorrect code could only
  5 + be triggered when checking linearization data, which must be
  6 + invoked explicitly. qpdf does not check linearization data when
  7 + reading or writing linearized files, but the qpdf --check command
  8 + does check linearization data.
  9 +
3 * Security fix: properly handle empty strings in 10 * Security fix: properly handle empty strings in
4 QPDF_Name::normalizeName. The empty string is not a valid name 11 QPDF_Name::normalizeName. The empty string is not a valid name
5 and would never be parsed as a name, so there were no known 12 and would never be parsed as a name, so there were no known
libqpdf/QPDF_linearization.cc
@@ -295,11 +295,25 @@ QPDF::readLinearizationData() @@ -295,11 +295,25 @@ QPDF::readLinearizationData()
295 readHPageOffset(BitStream(h_buf, h_size)); 295 readHPageOffset(BitStream(h_buf, h_size));
296 296
297 int HSi = HS.getIntValue(); 297 int HSi = HS.getIntValue();
  298 + if ((HSi < 0) || (HSi >= h_size))
  299 + {
  300 + throw QPDFExc(qpdf_e_damaged_pdf, this->file->getName(),
  301 + "linearization hint table",
  302 + this->file->getLastOffset(),
  303 + "/S (shared object) offset is out of bounds");
  304 + }
298 readHSharedObject(BitStream(h_buf + HSi, h_size - HSi)); 305 readHSharedObject(BitStream(h_buf + HSi, h_size - HSi));
299 306
300 if (HO.isInteger()) 307 if (HO.isInteger())
301 { 308 {
302 int HOi = HO.getIntValue(); 309 int HOi = HO.getIntValue();
  310 + if ((HOi < 0) || (HOi >= h_size))
  311 + {
  312 + throw QPDFExc(qpdf_e_damaged_pdf, this->file->getName(),
  313 + "linearization hint table",
  314 + this->file->getLastOffset(),
  315 + "/O (outline) offset is out of bounds");
  316 + }
303 readHGeneric(BitStream(h_buf + HOi, h_size - HOi), 317 readHGeneric(BitStream(h_buf + HOi, h_size - HOi),
304 this->outline_hints); 318 this->outline_hints);
305 } 319 }
qpdf/qtest/qpdf.test
@@ -199,7 +199,7 @@ $td-&gt;runtest(&quot;remove page we don&#39;t have&quot;, @@ -199,7 +199,7 @@ $td-&gt;runtest(&quot;remove page we don&#39;t have&quot;,
199 show_ntests(); 199 show_ntests();
200 # ---------- 200 # ----------
201 $td->notify("--- Miscellaneous Tests ---"); 201 $td->notify("--- Miscellaneous Tests ---");
202 -$n_tests += 67; 202 +$n_tests += 69;
203 203
204 $td->runtest("qpdf version", 204 $td->runtest("qpdf version",
205 {$td->COMMAND => "qpdf --version"}, 205 {$td->COMMAND => "qpdf --version"},
@@ -527,6 +527,16 @@ $td-&gt;runtest(&quot;ignore broken decode parms with no filters&quot;, @@ -527,6 +527,16 @@ $td-&gt;runtest(&quot;ignore broken decode parms with no filters&quot;,
527 {$td->FILE => "broken-decode-parms-no-filter.out", 527 {$td->FILE => "broken-decode-parms-no-filter.out",
528 $td->EXIT_STATUS => 0}, 528 $td->EXIT_STATUS => 0},
529 $td->NORMALIZE_NEWLINES); 529 $td->NORMALIZE_NEWLINES);
  530 +$td->runtest("bounds check linearization data 1",
  531 + {$td->COMMAND => "qpdf --check linearization-bounds-1.pdf"},
  532 + {$td->FILE => "linearization-bounds-1.out",
  533 + $td->EXIT_STATUS => 2},
  534 + $td->NORMALIZE_NEWLINES);
  535 +$td->runtest("bounds check linearization data 2",
  536 + {$td->COMMAND => "qpdf --check linearization-bounds-2.pdf"},
  537 + {$td->FILE => "linearization-bounds-2.out",
  538 + $td->EXIT_STATUS => 2},
  539 + $td->NORMALIZE_NEWLINES);
530 540
531 show_ntests(); 541 show_ntests();
532 # ---------- 542 # ----------
qpdf/qtest/qpdf/linearization-bounds-1.out 0 → 100644
  1 +checking linearization-bounds-1.pdf
  2 +PDF Version: 1.3
  3 +File is not encrypted
  4 +File is linearized
  5 +WARNING: linearization-bounds-1.pdf (linearization hint stream: object 62 0, file position 1183): attempting to recover stream length
  6 +linearization-bounds-1.pdf (linearization hint table, file position 1183): /S (shared object) offset is out of bounds
qpdf/qtest/qpdf/linearization-bounds-1.pdf 0 → 100644
No preview for this file type
qpdf/qtest/qpdf/linearization-bounds-2.out 0 → 100644
  1 +checking linearization-bounds-2.pdf
  2 +PDF Version: 1.3
  3 +File is not encrypted
  4 +File is linearized
  5 +WARNING: linearization-bounds-2.pdf (linearization hint stream: object 62 0, file position 1183): attempting to recover stream length
  6 +linearization-bounds-2.pdf (linearization hint table, file position 1183): /S (shared object) offset is out of bounds
qpdf/qtest/qpdf/linearization-bounds-2.pdf 0 → 100644
No preview for this file type