From 1c944e4c89cf09d86f4e3f79ff57d937dab9b60f Mon Sep 17 00:00:00 2001 From: Jay Berkenbilt Date: Sat, 14 Jul 2012 08:07:23 -0400 Subject: [PATCH] Have QPDFWriter detect foreign objects while writing Throw an exception that directs the user to QPDF::copyForeignObject. --- ChangeLog | 6 ++++++ libqpdf/QPDFWriter.cc | 9 +++++++++ qpdf/qpdf.testcov | 1 + qpdf/qtest/qpdf.test | 6 +++++- qpdf/qtest/qpdf/foreign-in-write.out | 2 ++ qpdf/test_driver.cc | 20 ++++++++++++++++++++ 6 files changed, 43 insertions(+), 1 deletion(-) create mode 100644 qpdf/qtest/qpdf/foreign-in-write.out diff --git a/ChangeLog b/ChangeLog index 29428ed3..5b150c27 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,9 @@ +2012-07-14 Jay Berkenbilt + + * QPDFWriter: detect if the user has inserted an indirect object + from another QPDF object and throw an exception directing the user + to copyForeignObject. + 2012-07-11 Jay Berkenbilt * Added new APIs to copy objects from one QPDF to another. This diff --git a/libqpdf/QPDFWriter.cc b/libqpdf/QPDFWriter.cc index a7c78b19..ce5cb3e0 100644 --- a/libqpdf/QPDFWriter.cc +++ b/libqpdf/QPDFWriter.cc @@ -761,6 +761,15 @@ QPDFWriter::enqueueObject(QPDFObjectHandle object) { if (object.isIndirect()) { + if (object.getOwningQPDF() != &(this->pdf)) + { + QTC::TC("qpdf", "QPDFWriter foreign object"); + throw std::logic_error( + "QPDFObjectHandle from different QPDF found while writing." + " Use QPDF::copyForeignObject to add objects from" + " another file."); + } + if (object.isNull()) { // This is a place-holder object for an object stream diff --git a/qpdf/qpdf.testcov b/qpdf/qpdf.testcov index ee257faa..a570f642 100644 --- a/qpdf/qpdf.testcov +++ b/qpdf/qpdf.testcov @@ -233,3 +233,4 @@ QPDF not crossing page boundary 0 QPDF replace foreign indirect with null 0 QPDF not copying pages object 0 QPDF insert foreign page 0 +QPDFWriter foreign object 0 diff --git a/qpdf/qtest/qpdf.test b/qpdf/qtest/qpdf.test index fc355666..221d0a8b 100644 --- a/qpdf/qtest/qpdf.test +++ b/qpdf/qtest/qpdf.test @@ -149,7 +149,7 @@ $td->runtest("remove page we don't have", $td->NORMALIZE_NEWLINES); # ---------- $td->notify("--- Miscellaneous Tests ---"); -$n_tests += 43; +$n_tests += 44; $td->runtest("qpdf version", {$td->COMMAND => "qpdf --version"}, @@ -365,6 +365,10 @@ $td->runtest("reserved objects", $td->runtest("check output", {$td->FILE => "a.pdf"}, {$td->FILE => "reserved-objects.pdf"}); +$td->runtest("detect foreign object in write", + {$td->COMMAND => "test_driver 29 copy-foreign-objects-in.pdf"}, + {$td->FILE => "foreign-in-write.out", $td->EXIT_STATUS => 0}, + $td->NORMALIZE_NEWLINES); show_ntests(); # ---------- diff --git a/qpdf/qtest/qpdf/foreign-in-write.out b/qpdf/qtest/qpdf/foreign-in-write.out new file mode 100644 index 00000000..14293aa9 --- /dev/null +++ b/qpdf/qtest/qpdf/foreign-in-write.out @@ -0,0 +1,2 @@ +logic error: QPDFObjectHandle from different QPDF found while writing. Use QPDF::copyForeignObject to add objects from another file. +test 29 done diff --git a/qpdf/test_driver.cc b/qpdf/test_driver.cc index d712d87d..4b2bc3d9 100644 --- a/qpdf/test_driver.cc +++ b/qpdf/test_driver.cc @@ -999,6 +999,26 @@ void runtest(int n, char const* filename) std::cout << "logic error: " << e.what() << std::endl; } } + else if (n == 29) + { + // Detect mixed objects in QPDFWriter + QPDF other; + other.processFile("minimal.pdf"); + // Should use copyForeignObject instead + other.getTrailer().replaceKey( + "/QTest", pdf.getTrailer().getKey("/QTest")); + + try + { + QPDFWriter w(other, "a.pdf"); + w.write(); + std::cout << "oops -- didn't throw" << std::endl; + } + catch (std::logic_error e) + { + std::cout << "logic error: " << e.what() << std::endl; + } + } else { throw std::runtime_error(std::string("invalid test ") +