Commit 4499e04b5714747eb954420f8133e650a5137d45
1 parent
35d72c82
better recovery for appended files with damaged cross-reference tables
git-svn-id: svn+q:///qpdf/trunk@649 71b93d88-0707-0410-a8cf-f5a4172ac649
Showing
4 changed files
with
37 additions
and
6 deletions
ChangeLog
| 1 | +2009-02-20 Jay Berkenbilt <ejb@ql.org> | |
| 2 | + | |
| 3 | + * libqpdf/QPDF.cc (QPDF::insertXrefEntry): when recovering the | |
| 4 | + cross-reference table, have objects we encounter later in the file | |
| 5 | + supersede those we found earlier. This improves the chances of | |
| 6 | + being able to recover appended files with damaged cross-reference | |
| 7 | + tables. | |
| 8 | + | |
| 1 | 9 | 2009-02-19 Jay Berkenbilt <ejb@ql.org> |
| 2 | 10 | |
| 3 | 11 | * libqpdf/Pl_LZWDecoder.cc: correct logic error for previously | ... | ... |
TODO
include/qpdf/QPDF.hh
| ... | ... | @@ -333,7 +333,8 @@ class QPDF |
| 333 | 333 | int read_xrefTable(off_t offset); |
| 334 | 334 | int read_xrefStream(off_t offset); |
| 335 | 335 | int processXRefStream(off_t offset, QPDFObjectHandle& xref_stream); |
| 336 | - void insertXrefEntry(int obj, int f0, int f1, int f2); | |
| 336 | + void insertXrefEntry(int obj, int f0, int f1, int f2, | |
| 337 | + bool overwrite = false); | |
| 337 | 338 | QPDFObjectHandle readObject( |
| 338 | 339 | InputSource*, int objid, int generation, |
| 339 | 340 | bool in_object_stream); | ... | ... |
libqpdf/QPDF.cc
| ... | ... | @@ -435,7 +435,7 @@ QPDF::reconstruct_xref(QPDFExc& e) |
| 435 | 435 | int obj = atoi(m.getMatch(1).c_str()); |
| 436 | 436 | int gen = atoi(m.getMatch(2).c_str()); |
| 437 | 437 | int offset = this->file.getLastOffset(); |
| 438 | - insertXrefEntry(obj, 1, offset, gen); | |
| 438 | + insertXrefEntry(obj, 1, offset, gen, true); | |
| 439 | 439 | } |
| 440 | 440 | else if ((! this->trailer.isInitialized()) && |
| 441 | 441 | trailer_re.match(line.c_str())) |
| ... | ... | @@ -865,11 +865,15 @@ QPDF::processXRefStream(off_t xref_offset, QPDFObjectHandle& xref_obj) |
| 865 | 865 | } |
| 866 | 866 | |
| 867 | 867 | void |
| 868 | -QPDF::insertXrefEntry(int obj, int f0, int f1, int f2) | |
| 868 | +QPDF::insertXrefEntry(int obj, int f0, int f1, int f2, bool overwrite) | |
| 869 | 869 | { |
| 870 | 870 | // Populate the xref table in such a way that the first reference |
| 871 | 871 | // to an object that we see, which is the one in the latest xref |
| 872 | - // table in which it appears, is the one that gets stored. | |
| 872 | + // table in which it appears, is the one that gets stored. This | |
| 873 | + // works because we are reading more recent appends before older | |
| 874 | + // ones. Exception: if overwrite is true, then replace any | |
| 875 | + // existing object. This is used in xref recovery mode, which | |
| 876 | + // reads the file from beginning to end. | |
| 873 | 877 | |
| 874 | 878 | // If there is already an entry for this object and generation in |
| 875 | 879 | // the table, it means that a later xref table has registered this |
| ... | ... | @@ -879,8 +883,16 @@ QPDF::insertXrefEntry(int obj, int f0, int f1, int f2) |
| 879 | 883 | ObjGen og(obj, gen); |
| 880 | 884 | if (this->xref_table.count(og)) |
| 881 | 885 | { |
| 882 | - QTC::TC("qpdf", "QPDF xref reused object"); | |
| 883 | - return; | |
| 886 | + if (overwrite) | |
| 887 | + { | |
| 888 | + QTC::TC("qpdf", "QPDF xref overwrite object"); | |
| 889 | + this->xref_table.erase(og); | |
| 890 | + } | |
| 891 | + else | |
| 892 | + { | |
| 893 | + QTC::TC("qpdf", "QPDF xref reused object"); | |
| 894 | + return; | |
| 895 | + } | |
| 884 | 896 | } |
| 885 | 897 | if (this->deleted_objects.count(obj)) |
| 886 | 898 | { | ... | ... |