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 | 7 | 2020-10-31 Jay Berkenbilt <ejb@ql.org> |
| 2 | 8 | |
| 3 | 9 | * 10.0.3: release | ... | ... |
libqpdf/QPDF.cc
| ... | ... | @@ -425,7 +425,20 @@ QPDF::parse(char const* password) |
| 425 | 425 | throw QPDFExc(qpdf_e_damaged_pdf, this->m->file->getName(), "", 0, |
| 426 | 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 | 443 | catch (QPDFExc& e) |
| 431 | 444 | { |
| ... | ... | @@ -1250,6 +1263,14 @@ QPDF::processXRefStream(qpdf_offset_t xref_offset, QPDFObjectHandle& xref_obj) |
| 1250 | 1263 | // This is needed by checkLinearization() |
| 1251 | 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 | 1274 | insertXrefEntry(obj, toI(fields[0]), |
| 1254 | 1275 | fields[1], toI(fields[2])); |
| 1255 | 1276 | } | ... | ... |
qpdf/qtest/qpdf.test
| ... | ... | @@ -1496,7 +1496,7 @@ $td->runtest("detect loops in pages structure", |
| 1496 | 1496 | show_ntests(); |
| 1497 | 1497 | # ---------- |
| 1498 | 1498 | $td->notify("--- Xref ---"); |
| 1499 | -$n_tests += 5; | |
| 1499 | +$n_tests += 6; | |
| 1500 | 1500 | |
| 1501 | 1501 | # Handle file with invalid xref table and object 0 as a regular object |
| 1502 | 1502 | # (bug 3159950). |
| ... | ... | @@ -1538,6 +1538,12 @@ $td->runtest("show number of pages", |
| 1538 | 1538 | {$td->STRING => "20\n", $td->EXIT_STATUS => 0}, |
| 1539 | 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 | 1547 | show_ntests(); |
| 1542 | 1548 | # ---------- |
| 1543 | 1549 | $td->notify("--- Overwrite self ---"); | ... | ... |
qpdf/qtest/qpdf/issue-150.out
| 1 | 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