From 4977a7efa5d0b2d10f57af646e54a91d94d088ab Mon Sep 17 00:00:00 2001 From: Jay Berkenbilt Date: Wed, 8 Apr 2020 18:47:29 -0400 Subject: [PATCH] Bug fix: getStreamData should on unfilterable stream (fixes #425) --- ChangeLog | 7 +++++++ libqpdf/QPDF_Stream.cc | 4 +++- qpdf/qtest/qpdf.test | 6 +++++- qpdf/qtest/qpdf/jpeg-qstream.pdf | Bin 0 -> 1156 bytes qpdf/qtest/qpdf/test68.out | 4 ++++ qpdf/test_driver.cc | 29 +++++++++++++++++++++++++++++ 6 files changed, 48 insertions(+), 2 deletions(-) create mode 100644 qpdf/qtest/qpdf/jpeg-qstream.pdf create mode 100644 qpdf/qtest/qpdf/test68.out diff --git a/ChangeLog b/ChangeLog index d9790438..8b85e41c 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,10 @@ +2020-04-08 Jay Berkenbilt + + * Bug fix: qpdf 10.0.0 introduced a bug in which + QPDFObjectHandle::getStreamData would return the raw data when + called on an unfilterable stream instead of throwing an exception + like it's supposed to. Fixes #425. + 2020-04-07 Jay Berkenbilt * Improve pdf-invert-images example to show a pattern of copying diff --git a/libqpdf/QPDF_Stream.cc b/libqpdf/QPDF_Stream.cc index 48c1ccf9..37ff9417 100644 --- a/libqpdf/QPDF_Stream.cc +++ b/libqpdf/QPDF_Stream.cc @@ -163,7 +163,9 @@ PointerHolder QPDF_Stream::getStreamData(qpdf_stream_decode_level_e decode_level) { Pl_Buffer buf("stream data buffer"); - if (! pipeStreamData(&buf, nullptr, 0, decode_level, false, false)) + bool filtered; + pipeStreamData(&buf, &filtered, 0, decode_level, false, false); + if (! filtered) { throw QPDFExc(qpdf_e_unsupported, qpdf->getFilename(), "", this->offset, diff --git a/qpdf/qtest/qpdf.test b/qpdf/qtest/qpdf.test index 788ef2dc..d7986c21 100644 --- a/qpdf/qtest/qpdf.test +++ b/qpdf/qtest/qpdf.test @@ -954,12 +954,16 @@ foreach (my $i = 1; $i <= 3; ++$i) show_ntests(); # ---------- $td->notify("--- Stream data ---"); -$n_tests += 1; +$n_tests += 2; $td->runtest("get stream data", {$td->COMMAND => "test_driver 11 stream-data.pdf"}, {$td->FILE => "test11.out", $td->EXIT_STATUS => 0}, $td->NORMALIZE_NEWLINES); +$td->runtest("get stream data fails on jpeg", + {$td->COMMAND => "test_driver 68 jpeg-qstream.pdf"}, + {$td->FILE => "test68.out", $td->EXIT_STATUS => 0}, + $td->NORMALIZE_NEWLINES); show_ntests(); # ---------- diff --git a/qpdf/qtest/qpdf/jpeg-qstream.pdf b/qpdf/qtest/qpdf/jpeg-qstream.pdf new file mode 100644 index 0000000000000000000000000000000000000000..8fce760d0aee1b6b28d3a0a06e8f7d41211b15e3 GIT binary patch literal 1156 zcmZWo+ins;7#?~cFg?-MTaz)7J9W>?k`UBFSMgK|B$_n67?y!<1G~-cv{J8p0pGwY zAHf&U3omGliB}$PtS{l6_|L*ZrT-*k_GA9j_x*piTDEU0w=|r6_vg)DtPq*_%|l!$ z5UEN#EF>x*H6rcSdBA9oXrs@@=@BDRiE`TYJET~|%xeih@jCV|`Ntk73XvYVt&r>y zJ#yVA(#Uxfe(EYB$F5s0534LF`Mo3GV-UrHWPaBV>POUp#ASBkI_zFRPl;r^UCsi) zN{upe{1*IupShg_4z)`4<0g+vt@NOqIQ6rg<{@)9k)FCOejwgGVqOPsijf!1gi)_} z_-*(LWggfS8zmA5CE%dpPgFwlbHc>$JlH~VL0Br8Tui1@7^hR|G+tg?#!IV9>GaC_ z%IaDsv!21r8=D)MO}J-<@6l2U!AT_6(eMMhA|n51ivrEeqGP4192fSBG#qHtmV=zzYjXda7;xdxx7k1jVcWU!(*LmEcA~92ZR?RU_+GA zMImMss8|G#z<275liUQEDtciSMCQ1hF~2(K80%$sDQ9EFrkwX*hxoi!{rp^O$m(vY zGXM6|tCxd2*RC%PzN7|H<;L09M(XT$uyQ_!J|@zGOC*Rg|}04XYf60Fp4#uSkb>owFi`xZFt1`ob1P|&<|J} z%f!O+#E5AannBuRf+;|fFyc+IT>cWKXx1f6H$li5UsHxHn!$1^EcFa#sTbn$fVy4S zAR&0o_r=OaD_?hCFtK=*GTAH0s;=rrQ!_ME(Q-|VnHJ4irs3rBPKzo|v7no}LN(cd m1vO>aP}_>5%S>sh?L4KXVHWpCt3?AIQDYev&StlFZ2S+NX)P`Q literal 0 HcmV?d00001 diff --git a/qpdf/qtest/qpdf/test68.out b/qpdf/qtest/qpdf/test68.out new file mode 100644 index 00000000..71647755 --- /dev/null +++ b/qpdf/qtest/qpdf/test68.out @@ -0,0 +1,4 @@ +get unfilterable stream: jpeg-qstream.pdf (offset 284): getStreamData called on unfilterable stream +filtered stream data okay +raw stream data okay +test 68 done diff --git a/qpdf/test_driver.cc b/qpdf/test_driver.cc index eba0903b..74aa7c26 100644 --- a/qpdf/test_driver.cc +++ b/qpdf/test_driver.cc @@ -2168,6 +2168,35 @@ void runtest(int n, char const* filename1, char const* arg2) w.setStaticID(true); w.write(); } + else if (n == 68) + { + QPDFObjectHandle root = pdf.getRoot(); + QPDFObjectHandle qstream = root.getKey("/QStream"); + try + { + qstream.getStreamData(); + std::cout << "oops -- didn't throw" << std::endl; + } + catch (std::exception& e) + { + std::cout << "get unfilterable stream: " << e.what() + << std::endl; + } + PointerHolder b1 = qstream.getStreamData(qpdf_dl_all); + if ((b1->getSize() > 10) && + (memcmp(b1->getBuffer(), + "wwwwwwwww", 9) == 0)) + { + std::cout << "filtered stream data okay" << std::endl; + } + PointerHolder b2 = qstream.getRawStreamData(); + if ((b2->getSize() > 10) && + (memcmp(b2->getBuffer(), + "\xff\xd8\xff\xe0\x00\x10\x4a\x46\x49\x46", 10) == 0)) + { + std::cout << "raw stream data okay" << std::endl; + } + } else { throw std::runtime_error(std::string("invalid test ") +