Commit b84f57e56d87691d6e592d1ff0b42d186cc70b98

Authored by Jay Berkenbilt
1 parent a2696ac2

Ignore broken DecodeParms for stream with no filters

ChangeLog
1 2013-07-07 Jay Berkenbilt <ejb@ql.org> 1 2013-07-07 Jay Berkenbilt <ejb@ql.org>
2 2
  3 + * Ignore error case of a stream's decode parameters having invalid
  4 + length when there are no stream filters.
  5 +
3 * qpdf: add --show-npages command-line option, which causes the 6 * qpdf: add --show-npages command-line option, which causes the
4 number of pages in the input file to be printed on a line by 7 number of pages in the input file to be printed on a line by
5 itself. 8 itself.
@@ -17,6 +17,10 @@ @@ -17,6 +17,10 @@
17 * Provide an option for QPDFWriter to preserve unreferenced objects 17 * Provide an option for QPDFWriter to preserve unreferenced objects
18 when writing out a file. 18 when writing out a file.
19 19
  20 + * Look at all the exceptions and error conditions in QPDF_stream and
  21 + figure out which ones should be converted to warnings and treating
  22 + the stream as not filterable.
  23 +
20 * If possible, support user-pluggable stream filters. This would 24 * If possible, support user-pluggable stream filters. This would
21 enable external code to provide interpretation for filters that are 25 enable external code to provide interpretation for filters that are
22 missing from qpdf. 26 missing from qpdf.
libqpdf/QPDF_Stream.cc
@@ -295,8 +295,13 @@ QPDF_Stream::filterable(std::vector&lt;std::string&gt;&amp; filters, @@ -295,8 +295,13 @@ QPDF_Stream::filterable(std::vector&lt;std::string&gt;&amp; filters,
295 } 295 }
296 } 296 }
297 297
298 - if (decode_parms.size() != filters.size()) 298 + // Ignore /DecodeParms entirely if /Filters is empty. At least
  299 + // one case of a file whose /DecodeParms was [ << >> ] when
  300 + // /Filters was empty has been seen in the wild.
  301 + if ((filters.size() != 0) && (decode_parms.size() != filters.size()))
299 { 302 {
  303 + // We should just issue a warning and treat this as not
  304 + // filterable.
300 throw QPDFExc(qpdf_e_damaged_pdf, qpdf->getFilename(), 305 throw QPDFExc(qpdf_e_damaged_pdf, qpdf->getFilename(),
301 "", this->offset, 306 "", this->offset,
302 "stream /DecodeParms length is" 307 "stream /DecodeParms length is"
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 += 66; 202 +$n_tests += 67;
203 203
204 $td->runtest("qpdf version", 204 $td->runtest("qpdf version",
205 {$td->COMMAND => "qpdf --version"}, 205 {$td->COMMAND => "qpdf --version"},
@@ -522,6 +522,11 @@ $td-&gt;runtest(&quot;show number of pages&quot;, @@ -522,6 +522,11 @@ $td-&gt;runtest(&quot;show number of pages&quot;,
522 "qpdf --show-npages 20-pages.pdf --password=user"}, 522 "qpdf --show-npages 20-pages.pdf --password=user"},
523 {$td->STRING => "20\n", $td->EXIT_STATUS => 0}, 523 {$td->STRING => "20\n", $td->EXIT_STATUS => 0},
524 $td->NORMALIZE_NEWLINES); 524 $td->NORMALIZE_NEWLINES);
  525 +$td->runtest("ignore broken decode parms with no filters",
  526 + {$td->COMMAND => "qpdf --check broken-decode-parms-no-filter.pdf"},
  527 + {$td->FILE => "broken-decode-parms-no-filter.out",
  528 + $td->EXIT_STATUS => 0},
  529 + $td->NORMALIZE_NEWLINES);
525 530
526 show_ntests(); 531 show_ntests();
527 # ---------- 532 # ----------
qpdf/qtest/qpdf/broken-decode-parms-no-filter.out 0 → 100644
  1 +checking broken-decode-parms-no-filter.pdf
  2 +PDF Version: 1.3
  3 +File is not encrypted
  4 +File is not linearized
  5 +No syntax or stream encoding errors found; the file may still contain
  6 +errors that qpdf cannot detect
qpdf/qtest/qpdf/broken-decode-parms-no-filter.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 + /Pages 2 0 R
  9 + /Type /Catalog
  10 +>>
  11 +endobj
  12 +
  13 +%% Original object ID: 2 0
  14 +2 0 obj
  15 +<<
  16 + /Count 1
  17 + /Kids [
  18 + 3 0 R
  19 + ]
  20 + /Type /Pages
  21 +>>
  22 +endobj
  23 +
  24 +%% Page 1
  25 +%% Original object ID: 3 0
  26 +3 0 obj
  27 +<<
  28 + /Contents 4 0 R
  29 + /MediaBox [
  30 + 0
  31 + 0
  32 + 612
  33 + 792
  34 + ]
  35 + /Parent 2 0 R
  36 + /Resources <<
  37 + /Font <<
  38 + /F1 6 0 R
  39 + >>
  40 + /ProcSet 7 0 R
  41 + >>
  42 + /Type /Page
  43 +>>
  44 +endobj
  45 +
  46 +%% Contents for page 1
  47 +%% Original object ID: 4 0
  48 +4 0 obj
  49 +<<
  50 + /Length 5 0 R
  51 + /DecodeParms [ << >> ]
  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 +0000000133 00000 n
  90 +0000000242 00000 n
  91 +0000000484 00000 n
  92 +0000000608 00000 n
  93 +0000000654 00000 n
  94 +0000000799 00000 n
  95 +trailer <<
  96 + /Root 1 0 R
  97 + /Size 8
  98 + /ID [<3ed0e583ae70f9665d727ef9c2780a19><3ed0e583ae70f9665d727ef9c2780a19>]
  99 +>>
  100 +startxref
  101 +834
  102 +%%EOF