From 9f8aba1db7f101e424cbc2c742abe92868cc4bff Mon Sep 17 00:00:00 2001 From: Jay Berkenbilt Date: Sat, 7 Jun 2014 12:31:22 -0400 Subject: [PATCH] Handle indirect stream filter/decode parameters QPDFWriter was trying to make /Filter and /DecodeParms direct in all cases, but there are some cases where /DecodeParms may refer to a stream, which can't be direct. QPDFWriter doesn't actually need /DecodeParms to be direct in that case because it won't be able to filter the stream. Until we can handle this type of stream, just don't make /Filter and /DecodeParms direct if we can't filter the stream anyway. Fixes #34 --- ChangeLog | 7 + libqpdf/QPDFWriter.cc | 8 +- qpdf/qtest/qpdf.test | 10 +- qpdf/qtest/qpdf/indirect-decode-parms-out.pdf | Bin 0 -> 1067 bytes qpdf/qtest/qpdf/indirect-decode-parms.pdf | 128 ++++++++++++++++++ 5 files changed, 150 insertions(+), 3 deletions(-) create mode 100644 qpdf/qtest/qpdf/indirect-decode-parms-out.pdf create mode 100644 qpdf/qtest/qpdf/indirect-decode-parms.pdf diff --git a/ChangeLog b/ChangeLog index d722e3c0..a83108cb 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,10 @@ +2014-06-07 Jay Berkenbilt + + * Bug fix: don't fail on files that contain streams where /Filter + or /DecodeParms references a stream. Before, qpdf would try to + convert these to direct objects, which would fail because of the + stream. + 2014-02-22 Jay Berkenbilt * Bug fix: if the last object in the first part of a linearized diff --git a/libqpdf/QPDFWriter.cc b/libqpdf/QPDFWriter.cc index 0f299a45..08647e37 100644 --- a/libqpdf/QPDFWriter.cc +++ b/libqpdf/QPDFWriter.cc @@ -2051,11 +2051,14 @@ QPDFWriter::prepareFileForWrite() { bool is_stream = false; bool is_root = false; + bool filterable = false; QPDFObjectHandle dict = node; if (node.isStream()) { is_stream = true; dict = node.getDict(); + // See whether we are able to filter this stream. + filterable = node.pipeStreamData(0, true, false, false); } else if (pdf.getRoot().getObjectID() == node.getObjectID()) { @@ -2073,8 +2076,9 @@ QPDFWriter::prepareFileForWrite() { if (oh.isIndirect() && ((key == "/Length") || - (key == "/Filter") || - (key == "/DecodeParms"))) + (filterable && + ((key == "/Filter") || + (key == "/DecodeParms"))))) { QTC::TC("qpdf", "QPDFWriter make stream key direct"); add_to_queue = false; diff --git a/qpdf/qtest/qpdf.test b/qpdf/qtest/qpdf.test index d54adc7e..8e697844 100644 --- a/qpdf/qtest/qpdf.test +++ b/qpdf/qtest/qpdf.test @@ -199,7 +199,7 @@ $td->runtest("remove page we don't have", show_ntests(); # ---------- $td->notify("--- Miscellaneous Tests ---"); -$n_tests += 70; +$n_tests += 72; $td->runtest("qpdf version", {$td->COMMAND => "qpdf --version"}, @@ -546,6 +546,14 @@ $td->runtest("sanity check array size", $td->EXIT_STATUS => 2}, $td->NORMALIZE_NEWLINES); +$td->runtest("stream with indirect decode parms", + {$td->COMMAND => + "qpdf --static-id indirect-decode-parms.pdf a.pdf"}, + {$td->STRING => "", $td->EXIT_STATUS => 0}); +$td->runtest("check file", + {$td->FILE => "a.pdf"}, + {$td->FILE => "indirect-decode-parms-out.pdf"}); + show_ntests(); # ---------- $td->notify("--- Numeric range parsing tests ---"); diff --git a/qpdf/qtest/qpdf/indirect-decode-parms-out.pdf b/qpdf/qtest/qpdf/indirect-decode-parms-out.pdf new file mode 100644 index 0000000000000000000000000000000000000000..4f6bd3573e9b50d347f0a477450a08d59fb301fa GIT binary patch literal 1067 zcmaiz&2G~`5XVaqQn18342VcYYP+`ApHdV-n_5YskR~Y{svb7UBsEHHWN&ET#0&5S zoOlFYfNQGqb%JvdJOekxtQ|K|dce8Z|IE((X6C=;W-Zt-Hn~>*_~-p!%>W(Z?sKhD z0oD{lOo5Zq0@iu;0)cG{DMs-Ss#Oi6z6vxK4%Dz0_pvFGlN7A{SP+gRCcxV93CiOz z8UlNS(NG?PX{#)$Oi-L?$Cx05DWntzxdwfzrK-$AX7v7d?NZ~R(a zIlWW*eT7g_6lJ#KNMa;Ya56Nuhy74&#S?E{?GxV{O5OjD!4V%jZC<8jiX@vB7y zlqG*Lz|9g>t8^lXdu^29T`KvGRND&+Qk4swS=W~L|E^Q*qSgF%$~(HbUusHXVxZ%n_JrmV4k_M=le`X1fK3n&OD5{?RgP7)kwI{2D? z`G8~F+=c;MY6k60JrK<`hwQSX87>WTNi!+avc@?vEyYwFsKH@{qtVqZ+cNCl06jiHVVGUtGh8%v8wXCc r!VUV> +endobj + +2 0 obj +<< + /Count 1 + /Kids [ + 3 0 R + ] + /Type /Pages +>> +endobj + +%% Page 1 +3 0 obj +<< + /Contents 4 0 R + /MediaBox [ + 0 + 0 + 612 + 792 + ] + /Parent 2 0 R + /Resources << + /Font << + /F1 6 0 R + >> + /ProcSet 7 0 R + >> + /Type /Page +>> +endobj + +%% Contents for page 1 +4 0 obj +<< + /Length 5 0 R +>> +stream +BT + /F1 24 Tf + 72 720 Td + (Potato) Tj +ET +endstream +endobj + +5 0 obj +44 +endobj + +6 0 obj +<< + /BaseFont /Helvetica + /Encoding /WinAnsiEncoding + /Name /F1 + /Subtype /Type1 + /Type /Font +>> +endobj + +7 0 obj +[ + /PDF + /Text +] +endobj + +8 0 obj +<< + /Length 9 0 R + /Filter /Something + /DecodeParms 10 0 R +>> +stream +here is some stream data +endstream +endobj + +9 0 obj +25 +endobj + +10 0 obj +<< + /Length 11 0 R +>> +stream +here is some stream data +endstream +endobj + +11 0 obj +25 +endobj + +xref +0 12 +0000000000 65535 f +0000000025 00000 n +0000000079 00000 n +0000000161 00000 n +0000000376 00000 n +0000000475 00000 n +0000000494 00000 n +0000000612 00000 n +0000000647 00000 n +0000000770 00000 n +0000000789 00000 n +0000000871 00000 n +trailer << + /Root 1 0 R + /Size 12 + /QTest 8 0 R + /ID [<3e1b045415cfe83fea12b9817e205ef6><3e1b045415cfe83fea12b9817e205ef6>] +>> +startxref +891 +%%EOF