aboutsummaryrefslogtreecommitdiffstats
path: root/qpdf
diff options
context:
space:
mode:
authorJay Berkenbilt <ejb@ql.org>2022-09-08 14:03:57 +0200
committerJay Berkenbilt <ejb@ql.org>2022-09-08 16:36:39 +0200
commitdba61da1bfb7e4d74c723f369d1c017df9707a14 (patch)
tree04c51f86dc066c710c23423fe178e051b20b49d9 /qpdf
parent264e25f391f83bcbeb60590f18ff96719b086454 (diff)
downloadqpdf-dba61da1bfb7e4d74c723f369d1c017df9707a14.tar.zst
Create a special "destroyed" type rather than using null
When a QPDF is destroyed, changing indirect objects to direct nulls makes them effectively disappear silently when they sneak into other places. Instead, we should treat this as an error. Adding a destroyed object type makes this possible.
Diffstat (limited to 'qpdf')
-rw-r--r--qpdf/qtest/qpdf/foreign-in-write.out1
-rw-r--r--qpdf/test_driver.cc43
2 files changed, 33 insertions, 11 deletions
diff --git a/qpdf/qtest/qpdf/foreign-in-write.out b/qpdf/qtest/qpdf/foreign-in-write.out
index a829577d..6fd0a4ee 100644
--- a/qpdf/qtest/qpdf/foreign-in-write.out
+++ b/qpdf/qtest/qpdf/foreign-in-write.out
@@ -1,3 +1,4 @@
logic error: QPDFObjectHandle from different QPDF found while writing. Use QPDF::copyForeignObject to add objects from another file.
+logic error: attempted to unparse a QPDFObjectHandle from a destroyed QPDF
logic error: Attempting to add an object from a different QPDF. 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 2446baf8..96d001d6 100644
--- a/qpdf/test_driver.cc
+++ b/qpdf/test_driver.cc
@@ -1135,8 +1135,8 @@ test_29(QPDF& pdf, char const* arg2)
{
// Detect mixed objects in QPDFWriter
assert(arg2 != 0);
- QPDF other;
- other.processFile(arg2);
+ auto other = QPDF::create();
+ other->processFile(arg2);
// We need to create a QPDF with mixed ownership to exercise
// QPDFWriter's ownership check. To do this, we have to sneak the
// foreign object inside an ownerless direct object to avoid
@@ -1146,10 +1146,25 @@ test_29(QPDF& pdf, char const* arg2)
// explicitly change the ownership to the wrong value.
auto dict = QPDFObjectHandle::newDictionary();
dict.replaceKey("/QTest", pdf.getTrailer().getKey("/QTest"));
- other.getTrailer().replaceKey("/QTest", dict);
+ other->getTrailer().replaceKey("/QTest", dict);
try {
- QPDFWriter w(other, "a.pdf");
+ QPDFWriter w(*other, "a.pdf");
+ w.write();
+ std::cout << "oops -- didn't throw" << std::endl;
+ } catch (std::logic_error const& e) {
+ std::cout << "logic error: " << e.what() << std::endl;
+ }
+
+ // Make sure deleting the other source doesn't prevent detection.
+ auto other2 = QPDF::create();
+ other2->emptyPDF();
+ dict = QPDFObjectHandle::newDictionary();
+ dict.replaceKey("/QTest", other2->getRoot());
+ other->getTrailer().replaceKey("/QTest", dict);
+ other2 = nullptr;
+ try {
+ QPDFWriter w(*other, "a.pdf");
w.write();
std::cout << "oops -- didn't throw" << std::endl;
} catch (std::logic_error const& e) {
@@ -1158,7 +1173,7 @@ test_29(QPDF& pdf, char const* arg2)
// Detect adding a foreign object
auto root1 = pdf.getRoot();
- auto root2 = other.getRoot();
+ auto root2 = other->getRoot();
try {
root1.replaceKey("/Oops", root2);
} catch (std::logic_error const& e) {
@@ -3300,14 +3315,20 @@ test_92(QPDF& pdf, char const* arg2)
check(resources);
check(contents);
check(contents_dict);
- // Objects that were originally indirect should be null.
+ // Objects that were originally indirect should be destroyed.
// Otherwise, they should have retained their old values. See
// comments in QPDFValueProxy::reset for why this is the case.
- assert(root.isNull());
- assert(page1.isNull());
- assert(contents.isNull());
- assert(!resources.isNull());
- assert(!contents_dict.isNull());
+ assert(root.isDestroyed());
+ assert(page1.isDestroyed());
+ assert(contents.isDestroyed());
+ assert(resources.isDictionary());
+ assert(contents_dict.isDictionary());
+ try {
+ root.unparse();
+ assert(false);
+ } catch (std::logic_error&) {
+ // Expected
+ }
}
static void