Commit 47f4ebcdac39256b084cdbb91ff04392fca4bb8d
1 parent
3e5aaa29
Ignore unused field in xref entry, avoiding range error (fixes #482)
Showing
6 changed files
with
45 additions
and
3 deletions
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& xref_obj) | @@ -1250,6 +1263,14 @@ QPDF::processXRefStream(qpdf_offset_t xref_offset, QPDFObjectHandle& 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->runtest("detect loops in pages structure", | @@ -1496,7 +1496,7 @@ $td->runtest("detect loops in pages structure", | ||
| 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->runtest("show number of pages", | @@ -1538,6 +1538,12 @@ $td->runtest("show number of pages", | ||
| 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
qpdf/qtest/qpdf/xref-range.pdf
0 → 100644
No preview for this file type