mirror of
https://github.com/qpdf/qpdf.git
synced 2024-12-22 10:58:58 +00:00
Alternative fix logic for fixDanglingReferences
This commit is contained in:
parent
008364a9a4
commit
cfcb279e49
@ -1173,6 +1173,7 @@ class QPDF
|
||||
void inParse(bool);
|
||||
void setTrailer(QPDFObjectHandle obj);
|
||||
void read_xref(qpdf_offset_t offset);
|
||||
bool resolveXRefTable();
|
||||
void reconstruct_xref(QPDFExc& e);
|
||||
bool
|
||||
parse_xrefFirst(std::string const& line, int& obj, int& num, int& bytes);
|
||||
@ -1202,10 +1203,10 @@ class QPDF
|
||||
bool attempt_recovery,
|
||||
qpdf_offset_t offset,
|
||||
std::string const& description,
|
||||
QPDFObjGen const& exp_og,
|
||||
QPDFObjGen exp_og,
|
||||
QPDFObjGen& og,
|
||||
bool skip_cache_if_in_xref);
|
||||
void resolve(QPDFObjGen const& og);
|
||||
void resolve(QPDFObjGen og);
|
||||
void resolveObjectsInStream(int obj_stream_number);
|
||||
void stopOnError(std::string const& message);
|
||||
QPDFObjectHandle reserveObjectIfNotExists(QPDFObjGen const& og);
|
||||
|
@ -1292,48 +1292,36 @@ QPDF::showXRefTable()
|
||||
}
|
||||
}
|
||||
|
||||
// Resolve all objects in the xref table. If this triggers a xref table
|
||||
// reconstruction abort and return false. Otherwise return true.
|
||||
bool
|
||||
QPDF::resolveXRefTable()
|
||||
{
|
||||
bool may_change = !this->m->reconstructed_xref;
|
||||
for (auto& iter: this->m->xref_table) {
|
||||
if (isUnresolved(iter.first)) {
|
||||
resolve(iter.first);
|
||||
if (may_change && this->m->reconstructed_xref) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
// 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) {
|
||||
if (this->m->fixed_dangling_refs) {
|
||||
return;
|
||||
}
|
||||
|
||||
// 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);
|
||||
}
|
||||
}
|
||||
|
||||
// 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.
|
||||
if (!resolveXRefTable()) {
|
||||
QTC::TC("qpdf", "QPDF fix dangling triggered xref reconstruction");
|
||||
fixDanglingReferences(force);
|
||||
} else {
|
||||
this->m->fixed_dangling_refs = true;
|
||||
resolveXRefTable();
|
||||
}
|
||||
this->m->fixed_dangling_refs = true;
|
||||
}
|
||||
|
||||
size_t
|
||||
@ -1356,7 +1344,7 @@ QPDF::getAllObjects()
|
||||
{
|
||||
// After fixDanglingReferences is called, all objects are in the
|
||||
// object cache.
|
||||
fixDanglingReferences(true);
|
||||
fixDanglingReferences();
|
||||
std::vector<QPDFObjectHandle> result;
|
||||
for (auto const& iter: this->m->obj_cache) {
|
||||
result.push_back(newIndirect(iter.first, iter.second.object));
|
||||
@ -1616,7 +1604,7 @@ QPDF::readObjectAtOffset(
|
||||
bool try_recovery,
|
||||
qpdf_offset_t offset,
|
||||
std::string const& description,
|
||||
QPDFObjGen const& exp_og,
|
||||
QPDFObjGen exp_og,
|
||||
QPDFObjGen& og,
|
||||
bool skip_cache_if_in_xref)
|
||||
{
|
||||
@ -1799,7 +1787,7 @@ QPDF::readObjectAtOffset(
|
||||
}
|
||||
|
||||
void
|
||||
QPDF::resolve(QPDFObjGen const& og)
|
||||
QPDF::resolve(QPDFObjGen og)
|
||||
{
|
||||
if (!isUnresolved(og)) {
|
||||
return;
|
||||
|
@ -2266,7 +2266,7 @@ QPDFWriter::prepareFileForWrite()
|
||||
// Make document extension level information direct as required by
|
||||
// the spec.
|
||||
|
||||
this->m->pdf.fixDanglingReferences(true);
|
||||
this->m->pdf.fixDanglingReferences();
|
||||
QPDFObjectHandle root = this->m->pdf.getRoot();
|
||||
for (auto const& key: root.getKeys()) {
|
||||
QPDFObjectHandle oh = root.getKey(key);
|
||||
|
Loading…
Reference in New Issue
Block a user