Commit 47f4ebcdac39256b084cdbb91ff04392fca4bb8d

Authored by Jay Berkenbilt
1 parent 3e5aaa29

Ignore unused field in xref entry, avoiding range error (fixes #482)

ChangeLog
  1 +2020-11-04 Jay Berkenbilt <ejb@ql.org>
  2 +
  3 + * Ignore the value of the offset/generation field in an xref entry
  4 + for a deleted object. Also attempt file recovery on lower-level
  5 + exceptions thrown while reading the xref table. Fixes #482.
  6 +
1 2020-10-31 Jay Berkenbilt <ejb@ql.org> 7 2020-10-31 Jay Berkenbilt <ejb@ql.org>
2 8
3 * 10.0.3: release 9 * 10.0.3: release
libqpdf/QPDF.cc
@@ -425,7 +425,20 @@ QPDF::parse(char const* password) @@ -425,7 +425,20 @@ QPDF::parse(char const* password)
425 throw QPDFExc(qpdf_e_damaged_pdf, this->m->file->getName(), "", 0, 425 throw QPDFExc(qpdf_e_damaged_pdf, this->m->file->getName(), "", 0,
426 "can't find startxref"); 426 "can't find startxref");
427 } 427 }
428 - read_xref(xref_offset); 428 + try
  429 + {
  430 + read_xref(xref_offset);
  431 + }
  432 + catch (QPDFExc&)
  433 + {
  434 + throw;
  435 + }
  436 + catch (std::exception& e)
  437 + {
  438 + throw QPDFExc(qpdf_e_damaged_pdf, this->m->file->getName(), "", 0,
  439 + std::string("error reading xref: ") + e.what());
  440 +
  441 + }
429 } 442 }
430 catch (QPDFExc& e) 443 catch (QPDFExc& e)
431 { 444 {
@@ -1250,6 +1263,14 @@ QPDF::processXRefStream(qpdf_offset_t xref_offset, QPDFObjectHandle&amp; xref_obj) @@ -1250,6 +1263,14 @@ QPDF::processXRefStream(qpdf_offset_t xref_offset, QPDFObjectHandle&amp; xref_obj)
1250 // This is needed by checkLinearization() 1263 // This is needed by checkLinearization()
1251 this->m->first_xref_item_offset = xref_offset; 1264 this->m->first_xref_item_offset = xref_offset;
1252 } 1265 }
  1266 + if (fields[0] == 0)
  1267 + {
  1268 + // Ignore fields[2], which we don't care about in this
  1269 + // case. This works around the issue of some PDF files
  1270 + // that put invalid values, like -1, here for deleted
  1271 + // objects.
  1272 + fields[2] = 0;
  1273 + }
1253 insertXrefEntry(obj, toI(fields[0]), 1274 insertXrefEntry(obj, toI(fields[0]),
1254 fields[1], toI(fields[2])); 1275 fields[1], toI(fields[2]));
1255 } 1276 }
qpdf/qtest/qpdf.test
@@ -1496,7 +1496,7 @@ $td-&gt;runtest(&quot;detect loops in pages structure&quot;, @@ -1496,7 +1496,7 @@ $td-&gt;runtest(&quot;detect loops in pages structure&quot;,
1496 show_ntests(); 1496 show_ntests();
1497 # ---------- 1497 # ----------
1498 $td->notify("--- Xref ---"); 1498 $td->notify("--- Xref ---");
1499 -$n_tests += 5; 1499 +$n_tests += 6;
1500 1500
1501 # Handle file with invalid xref table and object 0 as a regular object 1501 # Handle file with invalid xref table and object 0 as a regular object
1502 # (bug 3159950). 1502 # (bug 3159950).
@@ -1538,6 +1538,12 @@ $td-&gt;runtest(&quot;show number of pages&quot;, @@ -1538,6 +1538,12 @@ $td-&gt;runtest(&quot;show number of pages&quot;,
1538 {$td->STRING => "20\n", $td->EXIT_STATUS => 0}, 1538 {$td->STRING => "20\n", $td->EXIT_STATUS => 0},
1539 $td->NORMALIZE_NEWLINES); 1539 $td->NORMALIZE_NEWLINES);
1540 1540
  1541 +# Issue 482 -- don't range check fields[2] for xref entry type 0.
  1542 +$td->runtest("out of range in deleted object",
  1543 + {$td->COMMAND => "qpdf --check xref-range.pdf"},
  1544 + {$td->FILE => "xref-range.out", $td->EXIT_STATUS => 0},
  1545 + $td->NORMALIZE_NEWLINES);
  1546 +
1541 show_ntests(); 1547 show_ntests();
1542 # ---------- 1548 # ----------
1543 $td->notify("--- Overwrite self ---"); 1549 $td->notify("--- Overwrite self ---");
qpdf/qtest/qpdf/issue-150.out
1 WARNING: issue-150.pdf: can't find PDF header 1 WARNING: issue-150.pdf: can't find PDF header
2 -overflow/underflow converting 9900000000000000000 to 64-bit integer 2 +WARNING: issue-150.pdf: file is damaged
  3 +WARNING: issue-150.pdf: error reading xref: overflow/underflow converting 9900000000000000000 to 64-bit integer
  4 +WARNING: issue-150.pdf: Attempting to reconstruct cross-reference table
  5 +issue-150.pdf: unable to find trailer dictionary while recovering damaged file
qpdf/qtest/qpdf/xref-range.out 0 → 100644
  1 +checking xref-range.pdf
  2 +PDF Version: 1.5
  3 +File is not encrypted
  4 +File is not linearized
  5 +No syntax or stream encoding errors found; the file may still contain
  6 +errors that qpdf cannot detect
qpdf/qtest/qpdf/xref-range.pdf 0 → 100644
No preview for this file type