2
1
mirror of https://github.com/qpdf/qpdf.git synced 2025-01-03 15:17:29 +00:00

Fix logic for fixDanglingReferences

This commit is contained in:
Jay Berkenbilt 2022-11-26 16:43:41 -05:00 committed by Jay Berkenbilt
parent 1d9209ee74
commit ff42ea4e6c
3 changed files with 33 additions and 40 deletions

View File

@ -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) {
// 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);
if (this->m->reconstructed_xref) {
}
}
// 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;
}
}
}
}
// 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);
}
}
}
}
// Final pass adds all indirect references to the object cache.
for (auto const& iter: this->m->obj_cache) {
resolve(iter.first);
}
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;
}
}
size_t

View File

@ -678,3 +678,4 @@ QPDF_json bad pushedinheritedpageresources 0
QPDFPageObjectHelper copied fallback 0
QPDFPageObjectHelper used fallback without copying 0
QPDF skipping cache for known unchecked object 0
QPDF fix dangling triggered xref reconstruction 0

View File

@ -19,21 +19,13 @@ my $n_tests = 2 * scalar(@dangling);
foreach my $f (@dangling)
{
# TEMPORARY
my $xflags = 0;
if ($f eq 'dangling-bad-xref')
{
$xflags = $td->EXPECT_FAILURE;
}
# END TEMPORARY
$td->runtest("dangling refs: $f",
{$td->COMMAND => "test_driver 53 $f.pdf"},
{$td->FILE => "$f-dangling.out", $td->EXIT_STATUS => 0},
$td->NORMALIZE_NEWLINES | $xflags);
$td->NORMALIZE_NEWLINES);
$td->runtest("check output",
{$td->FILE => "a.pdf"},
{$td->FILE => "$f-dangling-out.pdf"},
$xflags);
{$td->FILE => "$f-dangling-out.pdf"});
}
cleanup();
$td->report($n_tests);