aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJay Berkenbilt <ejb@ql.org>2019-01-07 03:52:30 +0100
committerJay Berkenbilt <ejb@ql.org>2019-01-07 13:38:03 +0100
commitc3cee5f1549df6ba3a7829fcbf6a59739636bb88 (patch)
treecce647e1f70804903fb72e30349e23c3aba7a68b
parentfddbcab0e7cc5978802251696055efa64667f637 (diff)
downloadqpdf-c3cee5f1549df6ba3a7829fcbf6a59739636bb88.tar.zst
Exercise out of scope original pdf for copyForeignObject
-rw-r--r--libqpdf/QPDF.cc4
-rw-r--r--qpdf/qpdf.testcov2
-rw-r--r--qpdf/qtest/qpdf.test2
-rw-r--r--qpdf/qtest/qpdf/copy-foreign-objects-out3.pdf80
-rw-r--r--qpdf/test_driver.cc90
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<Buffer> b = p1.getBuffer();
+ Provider* provider = new Provider(b);
+ PointerHolder<QPDFObjectHandle::StreamDataProvider> 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();