Commit 4499e04b5714747eb954420f8133e650a5137d45

Authored by Jay Berkenbilt
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
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 2009-02-19 Jay Berkenbilt <ejb@ql.org> 9 2009-02-19 Jay Berkenbilt <ejb@ql.org>
2 10
3 * libqpdf/Pl_LZWDecoder.cc: correct logic error for previously 11 * libqpdf/Pl_LZWDecoder.cc: correct logic error for previously
  1 +2.0.4
  2 +=====
  3 +
  4 + * Spell check to fix types in messages and comments. Known type in
  5 + "damanged".
  6 +
  7 + * Exit with a different exit code if warning are found during check
  8 + mode.
  9 +
  10 +
1 General 11 General
2 ======= 12 =======
3 13
include/qpdf/QPDF.hh
@@ -333,7 +333,8 @@ class QPDF @@ -333,7 +333,8 @@ class QPDF
333 int read_xrefTable(off_t offset); 333 int read_xrefTable(off_t offset);
334 int read_xrefStream(off_t offset); 334 int read_xrefStream(off_t offset);
335 int processXRefStream(off_t offset, QPDFObjectHandle& xref_stream); 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 QPDFObjectHandle readObject( 338 QPDFObjectHandle readObject(
338 InputSource*, int objid, int generation, 339 InputSource*, int objid, int generation,
339 bool in_object_stream); 340 bool in_object_stream);
libqpdf/QPDF.cc
@@ -435,7 +435,7 @@ QPDF::reconstruct_xref(QPDFExc&amp; e) @@ -435,7 +435,7 @@ QPDF::reconstruct_xref(QPDFExc&amp; e)
435 int obj = atoi(m.getMatch(1).c_str()); 435 int obj = atoi(m.getMatch(1).c_str());
436 int gen = atoi(m.getMatch(2).c_str()); 436 int gen = atoi(m.getMatch(2).c_str());
437 int offset = this->file.getLastOffset(); 437 int offset = this->file.getLastOffset();
438 - insertXrefEntry(obj, 1, offset, gen); 438 + insertXrefEntry(obj, 1, offset, gen, true);
439 } 439 }
440 else if ((! this->trailer.isInitialized()) && 440 else if ((! this->trailer.isInitialized()) &&
441 trailer_re.match(line.c_str())) 441 trailer_re.match(line.c_str()))
@@ -865,11 +865,15 @@ QPDF::processXRefStream(off_t xref_offset, QPDFObjectHandle&amp; xref_obj) @@ -865,11 +865,15 @@ QPDF::processXRefStream(off_t xref_offset, QPDFObjectHandle&amp; xref_obj)
865 } 865 }
866 866
867 void 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 // Populate the xref table in such a way that the first reference 870 // Populate the xref table in such a way that the first reference
871 // to an object that we see, which is the one in the latest xref 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 // If there is already an entry for this object and generation in 878 // If there is already an entry for this object and generation in
875 // the table, it means that a later xref table has registered this 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,8 +883,16 @@ QPDF::insertXrefEntry(int obj, int f0, int f1, int f2)
879 ObjGen og(obj, gen); 883 ObjGen og(obj, gen);
880 if (this->xref_table.count(og)) 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 if (this->deleted_objects.count(obj)) 897 if (this->deleted_objects.count(obj))
886 { 898 {