From 2994f9cf4cc45e33406de34d4bce45ca491df98e Mon Sep 17 00:00:00 2001 From: Jay Berkenbilt Date: Sat, 6 Jan 2024 16:51:03 -0500 Subject: Attempt to find xref streams during recovery (fixes #1103) --- libqpdf/QPDF.cc | 32 ++++++++++++++++++++++++++++++++ 1 file changed, 32 insertions(+) (limited to 'libqpdf/QPDF.cc') diff --git a/libqpdf/QPDF.cc b/libqpdf/QPDF.cc index af3db080..67f5e2e0 100644 --- a/libqpdf/QPDF.cc +++ b/libqpdf/QPDF.cc @@ -579,6 +579,38 @@ QPDF::reconstruct_xref(QPDFExc& e) } m->deleted_objects.clear(); + if (!m->trailer.isInitialized()) { + qpdf_offset_t max_offset{0}; + // If there are any xref streams, take the last one to appear. + for (auto const& iter: m->xref_table) { + auto entry = iter.second; + if (entry.getType() != 1) { + continue; + } + auto oh = getObjectByObjGen(iter.first); + try { + if (!oh.isStreamOfType("/XRef")) { + continue; + } + } catch (std::exception&) { + continue; + } + auto offset = entry.getOffset(); + if (offset > max_offset) { + max_offset = offset; + setTrailer(oh.getDict()); + } + } + if (max_offset > 0) { + try { + read_xref(max_offset); + } catch (std::exception&) { + throw damagedPDF("", 0, "error decoding candidate xref stream while recovering damaged file"); + } + QTC::TC("qpdf", "QPDF recover xref stream"); + } + } + if (!m->trailer.isInitialized()) { // We could check the last encountered object to see if it was an xref stream. If so, we // could try to get the trailer from there. This may make it possible to recover files with -- cgit v1.2.3-54-g00ecf