summaryrefslogtreecommitdiffstats
path: root/libqpdf/QPDF.cc
diff options
context:
space:
mode:
authorJay Berkenbilt <ejb@ql.org>2022-11-26 22:43:41 +0100
committerJay Berkenbilt <jberkenbilt@users.noreply.github.com>2022-11-27 00:13:46 +0100
commitff42ea4e6cb8b03badf31993fcb4d9f57bb2ad1e (patch)
treee975aad05cbc029419ab75a090821e6a1a1d045d /libqpdf/QPDF.cc
parent1d9209ee743a34597de6965edf40333a3eca47b8 (diff)
downloadqpdf-ff42ea4e6cb8b03badf31993fcb4d9f57bb2ad1e.tar.zst
Fix logic for fixDanglingReferences
Diffstat (limited to 'libqpdf/QPDF.cc')
-rw-r--r--libqpdf/QPDF.cc60
1 files changed, 30 insertions, 30 deletions
diff --git a/libqpdf/QPDF.cc b/libqpdf/QPDF.cc
index 7e3326e8..89487ee1 100644
--- a/libqpdf/QPDF.cc
+++ b/libqpdf/QPDF.cc
@@ -1292,48 +1292,48 @@ QPDF::showXRefTable()
}
}
-// Ensure all objects in the pdf file, including those in indirect references,
-// appear in the object cache.
void
QPDF::fixDanglingReferences(bool force)
{
+ // Ensure all objects in the pdf file, including those in indirect
+ // references, appear in the object cache.
if (this->m->fixed_dangling_refs && !force) {
return;
}
- if (!this->m->fixed_dangling_refs) {
- // First pass is only run if the the xref table has not been
- // reconstructed. It will be terminated as soon as reconstruction is
- // triggered.
- if (!this->m->reconstructed_xref) {
- for (auto const& iter: this->m->xref_table) {
- auto og = iter.first;
- if (!isCached(og)) {
- m->obj_cache[og] =
- ObjCache(QPDF_Unresolved::create(this, og), -1, -1);
- if (this->m->reconstructed_xref) {
- break;
- }
- }
- }
- }
- // Second pass is skipped if the first pass did not trigger
- // reconstruction of the xref table.
- if (this->m->reconstructed_xref) {
- for (auto const& iter: this->m->xref_table) {
- auto og = iter.first;
- if (!isCached(og)) {
- m->obj_cache[og] =
- ObjCache(QPDF_Unresolved::create(this, og), -1, -1);
- }
- }
+ // Make sure everything in the xref table appears in the object
+ // cache.
+ for (auto const& iter: this->m->xref_table) {
+ auto og = iter.first;
+ if (!isCached(og)) {
+ m->obj_cache[og] =
+ ObjCache(QPDF_Unresolved::create(this, og), -1, -1);
}
}
- // Final pass adds all indirect references to the object cache.
+
+ // Resolve all known objects. The parser inserts any indirect
+ // reference into the object cache, including dangling references.
+ bool orig_reconstructed_xref = this->m->reconstructed_xref;
+ bool triggered_xref_reconstruction = false;
for (auto const& iter: this->m->obj_cache) {
resolve(iter.first);
+ if (!orig_reconstructed_xref && this->m->reconstructed_xref) {
+ triggered_xref_reconstruction = true;
+ // We triggered xref reconstruction. We'll have to start
+ // over.
+ break;
+ }
+ }
+ if (triggered_xref_reconstruction) {
+ // Resolving objects triggered xref reconstruction. This may
+ // cause new objects to appear in the xref. Start over again.
+ // This recursive call can never go more than two deep since
+ // we never clear this->m->reconstructed_xref.
+ QTC::TC("qpdf", "QPDF fix dangling triggered xref reconstruction");
+ fixDanglingReferences(force);
+ } else {
+ this->m->fixed_dangling_refs = true;
}
- this->m->fixed_dangling_refs = true;
}
size_t