Commit bf4b25b27ee61dcd57854e0fee1eae01a597cd10

Authored by m-holger
1 parent a9a3e5fd

Fix startxref recovery

Backup and restore the xref table during attempted startxref recovery to avoid corrupt states. Added a guard condition to handle invalid xref entries types, preventing processing of unsupported cases. These changes improve robustness during PDF parsing and recovery.
Showing 1 changed file with 7 additions and 0 deletions
libqpdf/QPDF_objects.cc
... ... @@ -256,10 +256,12 @@ QPDF::reconstruct_xref(QPDFExc& e, bool found_startxref)
256 256  
257 257 if (!found_startxref && !startxrefs.empty() && !found_objects.empty() &&
258 258 startxrefs.back() > std::get<2>(found_objects.back())) {
  259 + auto xref_backup{m->xref_table};
259 260 try {
260 261 m->file->seek(startxrefs.back(), SEEK_SET);
261 262 if (auto offset = QUtil::string_to_ll(readToken(*m->file).getValue().data())) {
262 263 read_xref(offset);
  264 +
263 265 if (getRoot().getKey("/Pages").isDictionary()) {
264 266 QTC::TC("qpdf", "QPDF startxref more than 1024 before end");
265 267 warn(damagedPDF(
... ... @@ -273,6 +275,7 @@ QPDF::reconstruct_xref(QPDFExc&amp; e, bool found_startxref)
273 275 } catch (...) {
274 276 // ok, bad luck. Do recovery.
275 277 }
  278 + m->xref_table = std::move(xref_backup);
276 279 }
277 280  
278 281 auto rend = found_objects.rend();
... ... @@ -1011,6 +1014,10 @@ QPDF::insertXrefEntry(int obj, int f0, qpdf_offset_t f1, int f2)
1011 1014 // later xref table has registered this object. Disregard this one.
1012 1015 int new_gen = f0 == 2 ? 0 : f2;
1013 1016  
  1017 + if (!(f0 == 1 || f0 == 2)) {
  1018 + return;
  1019 + }
  1020 +
1014 1021 if (!(obj > 0 && obj <= m->xref_table_max_id && 0 <= f2 && new_gen < 65535)) {
1015 1022 // We are ignoring invalid objgens. Most will arrive here from xref reconstruction. There
1016 1023 // is probably no point having another warning but we could count invalid items in order to
... ...