aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorm-holger <m-holger@kubitscheck.org>2022-08-10 14:16:06 +0200
committerm-holger <m-holger@kubitscheck.org>2022-09-01 15:47:24 +0200
commitc5d0428da21c9b2531fcf6b83f08a52eb7a86a4a (patch)
tree2b64bf105a184309302c533ed8a779a26724df3f
parent556c34f0f225bfc6eaeb617693e0161fbce5f2f3 (diff)
downloadqpdf-c5d0428da21c9b2531fcf6b83f08a52eb7a86a4a.tar.zst
Modify QPDF::getObject to not to resolve the object
-rw-r--r--libqpdf/QPDF.cc52
-rw-r--r--qpdf/qtest/qpdf/issue-51.out1
2 files changed, 32 insertions, 21 deletions
diff --git a/libqpdf/QPDF.cc b/libqpdf/QPDF.cc
index 80cc34cc..39043048 100644
--- a/libqpdf/QPDF.cc
+++ b/libqpdf/QPDF.cc
@@ -26,6 +26,7 @@
#include <qpdf/QPDF_Null.hh>
#include <qpdf/QPDF_Reserved.hh>
#include <qpdf/QPDF_Stream.hh>
+#include <qpdf/QPDF_Unresolved.hh>
#include <qpdf/QTC.hh>
#include <qpdf/QUtil.hh>
@@ -1397,7 +1398,7 @@ QPDF::fixDanglingReferences(bool force)
std::list<QPDFObjectHandle> queue;
queue.push_back(this->m->trailer);
for (auto const& og: to_process) {
- auto obj = getObjectByObjGen(og);
+ auto obj = getObject(og);
if (obj.isDictionary() || obj.isArray()) {
queue.push_back(obj);
} else if (obj.isStream()) {
@@ -1424,11 +1425,10 @@ QPDF::fixDanglingReferences(bool force)
}
for (auto sub: to_check) {
if (sub.isIndirect()) {
- if (sub.getOwningQPDF() == this) {
- if (!isCached(sub.getObjGen())) {
- QTC::TC("qpdf", "QPDF detected dangling ref");
- queue.push_back(sub);
- }
+ if ((sub.getOwningQPDF() == this) &&
+ isUnresolved(sub.getObjGen())) {
+ QTC::TC("qpdf", "QPDF detected dangling ref");
+ queue.push_back(sub);
}
} else {
queue.push_back(sub);
@@ -1885,7 +1885,7 @@ QPDF::readObjectAtOffset(
"expected endobj");
}
- if (!isCached(og)) {
+ if (isUnresolved(og)) {
// Store the object in the cache here so it gets cached
// whether we first know the offset or whether we first know
// the object ID and generation (in which we case we would get
@@ -1916,8 +1916,8 @@ QPDF::readObjectAtOffset(
}
}
qpdf_offset_t end_after_space = this->m->file->tell();
-
- this->m->obj_cache[og] = ObjCache(
+ updateCache(
+ og,
QPDFObjectHandle::ObjAccessor::getObject(oh),
end_before_space,
end_after_space);
@@ -1929,6 +1929,11 @@ QPDF::readObjectAtOffset(
std::shared_ptr<QPDFObject>
QPDF::resolve(QPDFObjGen const& og)
{
+ if (isCached(og) && !isUnresolved(og)) {
+ // We only need to resolve unresolved objects
+ return m->obj_cache[og].object;
+ }
+
// Check object cache before checking xref table. This allows us
// to insert things into the object cache that don't actually
// exist in the file.
@@ -1942,11 +1947,13 @@ QPDF::resolve(QPDFObjGen const& og)
"",
this->m->file->getLastOffset(),
("loop detected resolving object " + og.unparse(' ')));
- return QPDF_Null::create();
+
+ updateCache(og, QPDF_Null::create(), -1, -1);
+ return m->obj_cache[og].object;
}
ResolveRecorder rr(this, og);
- if ((!isCached(og)) && this->m->xref_table.count(og)) {
+ if (m->xref_table.count(og) != 0) {
QPDFXRefEntry const& entry = this->m->xref_table[og];
try {
switch (entry.getType()) {
@@ -1984,12 +1991,11 @@ QPDF::resolve(QPDFObjGen const& og)
": error reading object: " + e.what()));
}
}
- if (!isCached(og)) {
+
+ if (isUnresolved(og)) {
// PDF spec says unknown objects resolve to the null object.
QTC::TC("qpdf", "QPDF resolve failure to null");
- QPDFObjectHandle oh = QPDFObjectHandle::newNull();
- this->m->obj_cache[og] =
- ObjCache(QPDFObjectHandle::ObjAccessor::getObject(oh), -1, -1);
+ updateCache(og, QPDF_Null::create(), -1, -1);
}
std::shared_ptr<QPDFObject> result(this->m->obj_cache[og].object);
@@ -2084,15 +2090,15 @@ QPDF::resolveObjectsInStream(int obj_stream_number)
// objects appended to the file, so it is necessary to recheck the
// xref table and only cache what would actually be resolved here.
for (auto const& iter: offsets) {
- int obj = iter.first;
- QPDFObjGen og(obj, 0);
+ QPDFObjGen og(iter.first, 0);
QPDFXRefEntry const& entry = this->m->xref_table[og];
if ((entry.getType() == 2) &&
(entry.getObjStreamNumber() == obj_stream_number)) {
int offset = iter.second;
input->seek(offset, SEEK_SET);
QPDFObjectHandle oh = readObject(input, "", og, true);
- this->m->obj_cache[og] = ObjCache(
+ updateCache(
+ og,
QPDFObjectHandle::ObjAccessor::getObject(oh),
end_before_space,
end_after_space);
@@ -2176,8 +2182,14 @@ QPDF::reserveStream(QPDFObjGen const& og)
QPDFObjectHandle
QPDF::getObject(QPDFObjGen const& og)
{
- auto obj = (og.getObj() != 0) ? resolve(og) : QPDF_Null::create();
- return newIndirect(og, obj);
+ if (!og.isIndirect()) {
+ return QPDFObjectHandle::newNull();
+ }
+ // auto obj = (og.getObj() != 0) ? resolve(og) : QPDF_Null::create();
+ if (!m->obj_cache.count(og)) {
+ m->obj_cache[og] = ObjCache(QPDF_Unresolved::create(), -1, -1);
+ }
+ return newIndirect(og, m->obj_cache[og].object);
}
QPDFObjectHandle
diff --git a/qpdf/qtest/qpdf/issue-51.out b/qpdf/qtest/qpdf/issue-51.out
index b4bd165c..feffea44 100644
--- a/qpdf/qtest/qpdf/issue-51.out
+++ b/qpdf/qtest/qpdf/issue-51.out
@@ -9,7 +9,6 @@ WARNING: issue-51.pdf (object 2 0, offset 26): /Length key in stream dictionary
WARNING: issue-51.pdf (object 2 0, offset 71): attempting to recover stream length
WARNING: issue-51.pdf (object 2 0, offset 71): unable to recover stream data; treating stream as empty
WARNING: issue-51.pdf (object 2 0, offset 977): expected endobj
-WARNING: issue-51.pdf (object 2 0, offset 977): EOF after endobj
WARNING: issue-51.pdf (object 3 0): object has offset 0
WARNING: issue-51.pdf (object 4 0): object has offset 0
WARNING: issue-51.pdf (object 5 0): object has offset 0