From c3cee5f1549df6ba3a7829fcbf6a59739636bb88 Mon Sep 17 00:00:00 2001 From: Jay Berkenbilt Date: Sun, 6 Jan 2019 21:52:30 -0500 Subject: Exercise out of scope original pdf for copyForeignObject --- libqpdf/QPDF.cc | 4 +- qpdf/qpdf.testcov | 2 + qpdf/qtest/qpdf.test | 2 +- qpdf/qtest/qpdf/copy-foreign-objects-out3.pdf | 80 ++++++++++++++---------- qpdf/test_driver.cc | 90 ++++++++++++++++++--------- 5 files changed, 114 insertions(+), 64 deletions(-) diff --git a/libqpdf/QPDF.cc b/libqpdf/QPDF.cc index c5172fd7..e49f0ce3 100644 --- a/libqpdf/QPDF.cc +++ b/libqpdf/QPDF.cc @@ -2380,7 +2380,7 @@ QPDF::replaceForeignIndirectObjects( stream->getStreamDataProvider(); if (stream_buffer.getPointer()) { -// QTC::TC("qpdf", "QPDF copy foreign stream with buffer"); + QTC::TC("qpdf", "QPDF copy foreign stream with buffer"); result.replaceStreamData(stream_buffer, dict.getKey("/Filter"), dict.getKey("/DecodeParms")); @@ -2388,7 +2388,7 @@ QPDF::replaceForeignIndirectObjects( else if (stream_provider.getPointer()) { // In this case, the remote stream's QPDF must stay in scope. -// QTC::TC("qpdf", "QPDF copy foreign stream with provider"); + QTC::TC("qpdf", "QPDF copy foreign stream with provider"); this->m->copied_stream_data_provider->registerForeignStream( local_og, foreign); result.replaceStreamData(this->m->copied_streams, diff --git a/qpdf/qpdf.testcov b/qpdf/qpdf.testcov index 6a9c90d7..801004f3 100644 --- a/qpdf/qpdf.testcov +++ b/qpdf/qpdf.testcov @@ -408,3 +408,5 @@ qpdf image optimize too small 0 QPDFFormFieldObjectHelper WinAnsi 0 QPDF_encryption attachment stream 0 QPDF pipe foreign encrypted stream 0 +QPDF copy foreign stream with provider 0 +QPDF copy foreign stream with buffer 0 diff --git a/qpdf/qtest/qpdf.test b/qpdf/qtest/qpdf.test index d1ff01cf..c36b8c95 100644 --- a/qpdf/qtest/qpdf.test +++ b/qpdf/qtest/qpdf.test @@ -1921,7 +1921,7 @@ foreach my $d ([25, 1], [26, 2], [27, 3]) my ($testn, $outn) = @$d; $td->runtest("copy objects $outn", {$td->COMMAND => "test_driver $testn" . - " copy-foreign-objects-in.pdf minimal.pdf"}, + " minimal.pdf copy-foreign-objects-in.pdf"}, {$td->STRING => "test $testn done\n", $td->EXIT_STATUS => 0}, $td->NORMALIZE_NEWLINES); $td->runtest("check output", diff --git a/qpdf/qtest/qpdf/copy-foreign-objects-out3.pdf b/qpdf/qtest/qpdf/copy-foreign-objects-out3.pdf index f2911a2d..f2d6bad6 100644 --- a/qpdf/qtest/qpdf/copy-foreign-objects-out3.pdf +++ b/qpdf/qtest/qpdf/copy-foreign-objects-out3.pdf @@ -1,45 +1,57 @@ %PDF-1.3 %¿÷¢þ 1 0 obj -<< /Pages 3 0 R /Type /Catalog >> +<< /Pages 5 0 R /Type /Catalog >> endobj 2 0 obj -<< /O1 4 0 R /O2 5 0 R /O3 6 0 R /This-is-QTest true >> +<< /O1 6 0 R /O2 7 0 R /O3 8 0 R /This-is-QTest true >> endobj 3 0 obj -<< /Count 3 /Kids [ 7 0 R 8 0 R 6 0 R ] /Type /Pages >> +<< /Length 20 >> +stream +new data for stream +endstream endobj 4 0 obj -[ /This-is-O1 /potato << /O2 [ 3.14159 << /O2 5 0 R >> 2.17828 ] >> /salad /O2 5 0 R /Stream1 9 0 R ] +<< /Length 7 >> +stream +potato +endstream endobj 5 0 obj -<< /K1 [ 2.236 /O1 4 0 R 1.732 ] /O1 4 0 R /This-is-O2 true >> +<< /Count 3 /Kids [ 9 0 R 10 0 R 8 0 R ] /Type /Pages >> endobj 6 0 obj -<< /Contents 10 0 R /MediaBox [ 0 0 612 792 ] /OtherPage 8 0 R /Parent 3 0 R /Resources << /Font << /F1 11 0 R >> /ProcSet [ /PDF /Text ] >> /Rotate 180 /This-is-O3 true /Type /Page >> +[ /This-is-O1 /potato << /O2 [ 3.14159 << /O2 7 0 R >> 2.17828 ] >> /salad /O2 7 0 R /Stream1 11 0 R ] endobj 7 0 obj -<< /Contents 12 0 R /MediaBox [ 0 0 612 792 ] /Parent 3 0 R /Resources << /Font << /F1 13 0 R >> /ProcSet 14 0 R >> /Type /Page >> +<< /K1 [ 2.236 /O1 6 0 R 1.732 ] /O1 6 0 R /This-is-O2 true >> endobj 8 0 obj -<< /Contents 15 0 R /MediaBox [ 0 0 612 792 ] /Parent 3 0 R /Resources << /Font << /F1 11 0 R >> /ProcSet [ /PDF /Text ] >> /Rotate 180 /This-is-O3-other-page true /Type /Page >> +<< /Contents 12 0 R /MediaBox [ 0 0 612 792 ] /OtherPage 10 0 R /Parent 5 0 R /Resources << /Font << /F1 13 0 R >> /ProcSet [ /PDF /Text ] >> /Rotate 180 /This-is-O3 true /Type /Page >> endobj 9 0 obj -<< /Stream2 16 0 R /This-is-Stream1 true /Length 18 >> +<< /Contents 14 0 R /MediaBox [ 0 0 612 792 ] /Parent 5 0 R /Resources << /Font << /F1 15 0 R >> /ProcSet 16 0 R >> /Type /Page >> +endobj +10 0 obj +<< /Contents 17 0 R /MediaBox [ 0 0 612 792 ] /Parent 5 0 R /Resources << /Font << /F1 13 0 R >> /ProcSet [ /PDF /Text ] >> /Rotate 180 /This-is-O3-other-page true /Type /Page >> +endobj +11 0 obj +<< /Stream2 18 0 R /This-is-Stream1 true /Length 18 >> stream This is stream 1. endstream endobj -10 0 obj +12 0 obj << /Length 47 >> stream BT /F1 15 Tf 72 720 Td (Original page 2) Tj ET endstream endobj -11 0 obj +13 0 obj << /BaseFont /Times-Roman /Encoding /WinAnsiEncoding /Subtype /Type1 /Type /Font >> endobj -12 0 obj +14 0 obj << /Length 44 >> stream BT @@ -49,44 +61,46 @@ BT ET endstream endobj -13 0 obj +15 0 obj << /BaseFont /Helvetica /Encoding /WinAnsiEncoding /Name /F1 /Subtype /Type1 /Type /Font >> endobj -14 0 obj +16 0 obj [ /PDF /Text ] endobj -15 0 obj +17 0 obj << /Length 47 >> stream BT /F1 15 Tf 72 720 Td (Original page 3) Tj ET endstream endobj -16 0 obj -<< /Stream1 9 0 R /This-is-Stream2 true /Length 18 >> +18 0 obj +<< /Stream1 11 0 R /This-is-Stream2 true /Length 18 >> stream This is stream 2. endstream endobj xref -0 17 +0 19 0000000000 65535 f 0000000015 00000 n 0000000064 00000 n 0000000135 00000 n -0000000206 00000 n -0000000323 00000 n -0000000401 00000 n -0000000601 00000 n -0000000747 00000 n -0000000941 00000 n -0000001046 00000 n -0000001143 00000 n -0000001243 00000 n -0000001337 00000 n -0000001445 00000 n -0000001476 00000 n -0000001573 00000 n -trailer << /QTest 2 0 R /Root 1 0 R /Size 17 /ID [<31415926535897932384626433832795><31415926535897932384626433832795>] >> +0000000204 00000 n +0000000259 00000 n +0000000331 00000 n +0000000449 00000 n +0000000527 00000 n +0000000728 00000 n +0000000874 00000 n +0000001069 00000 n +0000001175 00000 n +0000001272 00000 n +0000001372 00000 n +0000001466 00000 n +0000001574 00000 n +0000001605 00000 n +0000001702 00000 n +trailer << /QTest 2 0 R /QTest2 [ 3 0 R 4 0 R ] /Root 1 0 R /Size 19 /ID [<31415926535897932384626433832795><31415926535897932384626433832795>] >> startxref -1678 +1808 %%EOF diff --git a/qpdf/test_driver.cc b/qpdf/test_driver.cc index 8031d0cc..71078618 100644 --- a/qpdf/test_driver.cc +++ b/qpdf/test_driver.cc @@ -1085,13 +1085,16 @@ void runtest(int n, char const* filename1, char const* arg2) // and O2 and their streams but not O3 or any other pages. assert(arg2 != 0); - QPDF newpdf; - newpdf.processFile(arg2); - QPDFObjectHandle qtest = pdf.getTrailer().getKey("/QTest"); - newpdf.getTrailer().replaceKey( - "/QTest", newpdf.copyForeignObject(qtest)); + { + // Make sure original PDF is out of scope when we write. + QPDF oldpdf; + oldpdf.processFile(arg2); + QPDFObjectHandle qtest = oldpdf.getTrailer().getKey("/QTest"); + pdf.getTrailer().replaceKey( + "/QTest", pdf.copyForeignObject(qtest)); + } - QPDFWriter w(newpdf, "a.pdf"); + QPDFWriter w(pdf, "a.pdf"); w.setStaticID(true); w.setStreamDataMode(qpdf_s_preserve); w.write(); @@ -1104,16 +1107,19 @@ void runtest(int n, char const* filename1, char const* arg2) // that O3 points to. Also, inherited object will have been // pushed down and will be preserved. - assert(arg2 != 0); - QPDF newpdf; - newpdf.processFile(arg2); - QPDFObjectHandle qtest = pdf.getTrailer().getKey("/QTest"); - QPDFObjectHandle O3 = qtest.getKey("/O3"); - QPDFPageDocumentHelper(newpdf).addPage(O3, false); - newpdf.getTrailer().replaceKey( - "/QTest", newpdf.copyForeignObject(qtest)); + { + // Make sure original PDF is out of scope when we write. + assert(arg2 != 0); + QPDF oldpdf; + oldpdf.processFile(arg2); + QPDFObjectHandle qtest = oldpdf.getTrailer().getKey("/QTest"); + QPDFObjectHandle O3 = qtest.getKey("/O3"); + QPDFPageDocumentHelper(pdf).addPage(O3, false); + pdf.getTrailer().replaceKey( + "/QTest", pdf.copyForeignObject(qtest)); + } - QPDFWriter w(newpdf, "a.pdf"); + QPDFWriter w(pdf, "a.pdf"); w.setStaticID(true); w.setStreamDataMode(qpdf_s_preserve); w.write(); @@ -1122,20 +1128,48 @@ void runtest(int n, char const* filename1, char const* arg2) { // Copy O3 and the page O3 refers to before copying qtest. // Should get qtest plus only the O3 page and the page that O3 - // points to. Inherited objects should be preserved. + // points to. Inherited objects should be preserved. This test + // also exercises copying from a stream that has a buffer and + // a provider, including copying a provider multiple times. - assert(arg2 != 0); - QPDF newpdf; - newpdf.processFile(arg2); - QPDFObjectHandle qtest = pdf.getTrailer().getKey("/QTest"); - QPDFObjectHandle O3 = qtest.getKey("/O3"); - QPDFPageDocumentHelper dh(newpdf); - dh.addPage(O3.getKey("/OtherPage"), false); - dh.addPage(O3, false); - newpdf.getTrailer().replaceKey( - "/QTest", newpdf.copyForeignObject(qtest)); - - QPDFWriter w(newpdf, "a.pdf"); + Pl_Buffer p1("buffer"); + p1.write(QUtil::unsigned_char_pointer("new data for stream\n"), + 20); // no null! + p1.finish(); + PointerHolder b = p1.getBuffer(); + Provider* provider = new Provider(b); + PointerHolder p = provider; + QPDF empty1; + empty1.emptyPDF(); + QPDFObjectHandle s1 = QPDFObjectHandle::newStream(&empty1); + s1.replaceStreamData( + p, QPDFObjectHandle::newNull(), QPDFObjectHandle::newNull()); + QPDF empty2; + empty2.emptyPDF(); + s1 = empty2.copyForeignObject(s1); + { + // Make sure original PDF is out of scope when we write. + assert(arg2 != 0); + QPDF oldpdf; + oldpdf.processFile(arg2); + QPDFObjectHandle qtest = oldpdf.getTrailer().getKey("/QTest"); + QPDFObjectHandle O3 = qtest.getKey("/O3"); + QPDFPageDocumentHelper dh(pdf); + dh.addPage(O3.getKey("/OtherPage"), false); + dh.addPage(O3, false); + QPDFObjectHandle s2 = QPDFObjectHandle::newStream( + &oldpdf, "potato\n"); + pdf.getTrailer().replaceKey( + "/QTest", pdf.copyForeignObject(qtest)); + pdf.getTrailer().replaceKey( + "/QTest2", QPDFObjectHandle::newArray()); + pdf.getTrailer().getKey("/QTest2").appendItem( + pdf.copyForeignObject(s1)); + pdf.getTrailer().getKey("/QTest2").appendItem( + pdf.copyForeignObject(s2)); + } + + QPDFWriter w(pdf, "a.pdf"); w.setStaticID(true); w.setStreamDataMode(qpdf_s_preserve); w.write(); -- cgit v1.2.3-54-g00ecf