Commit c729e07d55c870e7e08f158f0a80a3d452c59cdc

Authored by Jay Berkenbilt
1 parent d8900c22

Avoid resolving arguments to R

When checking two objects preceding R while parsing, ensure that the
objects are direct. This avoids stuff like 1 0 obj containing 1 0 R 0 R
from causing an infinite loop in object resolution.
ChangeLog
  1 +2015-02-21 Jay Berkenbilt <ejb@ql.org>
  2 +
  3 + * Ensure that arguments to "R" when parsing the file are direct
  4 + objects before trying to resolve them. This prevents specially
  5 + crafted files from causing qpdf to crash with a stack overflow.
  6 + Thanks to Gynvael Coldwind and Mateusz Jurczyk of the Google
  7 + Security Team for providing a sample file with this problem.
  8 +
1 9 2014-12-01 Jay Berkenbilt <ejb@ql.org>
2 10  
3 11 * Some broken PDF files lack the required /Type key for /Page and
... ...
libqpdf/QPDFObjectHandle.cc
... ... @@ -966,7 +966,9 @@ QPDFObjectHandle::parseInternal(PointerHolder&lt;InputSource&gt; input,
966 966 std::string const& value = token.getValue();
967 967 if ((value == "R") && (in_array || in_dictionary) &&
968 968 (olist.size() >= 2) &&
  969 + (! olist.at(olist.size() - 1).isIndirect()) &&
969 970 (olist.at(olist.size() - 1).isInteger()) &&
  971 + (! olist.at(olist.size() - 2).isIndirect()) &&
970 972 (olist.at(olist.size() - 2).isInteger()))
971 973 {
972 974 if (context == 0)
... ...
qpdf/qtest/qpdf.test
... ... @@ -199,7 +199,7 @@ $td-&gt;runtest(&quot;remove page we don&#39;t have&quot;,
199 199 show_ntests();
200 200 # ----------
201 201 $td->notify("--- Miscellaneous Tests ---");
202   -$n_tests += 74;
  202 +$n_tests += 75;
203 203  
204 204 $td->runtest("qpdf version",
205 205 {$td->COMMAND => "qpdf --version"},
... ... @@ -562,6 +562,10 @@ $td-&gt;runtest(&quot;no type key for page nodes&quot;,
562 562 {$td->COMMAND => "qpdf --check no-pages-types.pdf"},
563 563 {$td->FILE => "no-pages-types.out", $td->EXIT_STATUS => 0},
564 564 $td->NORMALIZE_NEWLINES);
  565 +$td->runtest("ensure arguments to R are direct",
  566 + {$td->COMMAND => "qpdf --check indirect-r-arg.pdf"},
  567 + {$td->FILE => "indirect-r-arg.out", $td->EXIT_STATUS => 2},
  568 + $td->NORMALIZE_NEWLINES);
565 569  
566 570 show_ntests();
567 571 # ----------
... ...
qpdf/qtest/qpdf/indirect-r-arg.out 0 → 100644
  1 +indirect-r-arg.pdf (file position 76): unknown token while reading object (R)
... ...
qpdf/qtest/qpdf/indirect-r-arg.pdf 0 → 100644
  1 +%PDF-1.3
  2 +%¿÷¢þ
  3 +%QDF-1.0
  4 +
  5 +%% Original object ID: 1 0
  6 +1 0 obj
  7 +<<
  8 + /X 1 0 R 0 R
  9 + /Pages 2 0 R
  10 + /Type /Catalog
  11 +>>
  12 +endobj
  13 +
  14 +%% Original object ID: 2 0
  15 +2 0 obj
  16 +<<
  17 + /Count 1
  18 + /Kids [
  19 + 3 0 R
  20 + ]
  21 + /Type /Pages
  22 +>>
  23 +endobj
  24 +
  25 +%% Page 1
  26 +%% Original object ID: 3 0
  27 +3 0 obj
  28 +<<
  29 + /Contents 4 0 R
  30 + /MediaBox [
  31 + 0
  32 + 0
  33 + 612
  34 + 792
  35 + ]
  36 + /Parent 2 0 R
  37 + /Resources <<
  38 + /Font <<
  39 + /F1 6 0 R
  40 + >>
  41 + /ProcSet 7 0 R
  42 + >>
  43 + /Type /Page
  44 +>>
  45 +endobj
  46 +
  47 +%% Contents for page 1
  48 +%% Original object ID: 4 0
  49 +4 0 obj
  50 +<<
  51 + /Length 5 0 R
  52 +>>
  53 +stream
  54 +BT
  55 + /F1 24 Tf
  56 + 72 720 Td
  57 + (Potato) Tj
  58 +ET
  59 +endstream
  60 +endobj
  61 +
  62 +5 0 obj
  63 +44
  64 +endobj
  65 +
  66 +%% Original object ID: 6 0
  67 +6 0 obj
  68 +<<
  69 + /BaseFont /Helvetica
  70 + /Encoding /WinAnsiEncoding
  71 + /Name /F1
  72 + /Subtype /Type1
  73 + /Type /Font
  74 +>>
  75 +endobj
  76 +
  77 +%% Original object ID: 5 0
  78 +7 0 obj
  79 +[
  80 + /PDF
  81 + /Text
  82 +]
  83 +endobj
  84 +
  85 +xref
  86 +0 8
  87 +0000000000 65535 f
  88 +0000000052 00000 n
  89 +0000000148 00000 n
  90 +0000000257 00000 n
  91 +0000000499 00000 n
  92 +0000000598 00000 n
  93 +0000000644 00000 n
  94 +0000000789 00000 n
  95 +trailer <<
  96 + /Root 1 0 R
  97 + /Size 8
  98 + /ID [<9e2756c6254602d0b896148e97ee7414><9e2756c6254602d0b896148e97ee7414>]
  99 +>>
  100 +startxref
  101 +824
  102 +%%EOF
... ...