Exercise out of scope original pdf for copyForeignObject

This commit is contained in:
Jay Berkenbilt 2019-01-06 21:52:30 -05:00
parent fddbcab0e7
commit c3cee5f154
5 changed files with 113 additions and 63 deletions

View File

@ -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,

View File

@ -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

View File

@ -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",

View File

@ -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

View File

@ -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));
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(newpdf, "a.pdf");
QPDFWriter w(pdf, "a.pdf");
w.setStaticID(true);
w.setStreamDataMode(qpdf_s_preserve);
w.write();