From 4499e04b5714747eb954420f8133e650a5137d45 Mon Sep 17 00:00:00 2001 From: Jay Berkenbilt Date: Sat, 21 Feb 2009 02:31:32 +0000 Subject: [PATCH] better recovery for appended files with damaged cross-reference tables git-svn-id: svn+q:///qpdf/trunk@649 71b93d88-0707-0410-a8cf-f5a4172ac649 --- ChangeLog | 8 ++++++++ TODO | 10 ++++++++++ include/qpdf/QPDF.hh | 3 ++- libqpdf/QPDF.cc | 22 +++++++++++++++++----- 4 files changed, 37 insertions(+), 6 deletions(-) diff --git a/ChangeLog b/ChangeLog index e327b7b3..da5150df 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,11 @@ +2009-02-20 Jay Berkenbilt + + * libqpdf/QPDF.cc (QPDF::insertXrefEntry): when recovering the + cross-reference table, have objects we encounter later in the file + supersede those we found earlier. This improves the chances of + being able to recover appended files with damaged cross-reference + tables. + 2009-02-19 Jay Berkenbilt * libqpdf/Pl_LZWDecoder.cc: correct logic error for previously diff --git a/TODO b/TODO index d705187e..e5097fb7 100644 --- a/TODO +++ b/TODO @@ -1,3 +1,13 @@ +2.0.4 +===== + + * Spell check to fix types in messages and comments. Known type in + "damanged". + + * Exit with a different exit code if warning are found during check + mode. + + General ======= diff --git a/include/qpdf/QPDF.hh b/include/qpdf/QPDF.hh index db5c91e6..f57d4c94 100644 --- a/include/qpdf/QPDF.hh +++ b/include/qpdf/QPDF.hh @@ -333,7 +333,8 @@ class QPDF int read_xrefTable(off_t offset); int read_xrefStream(off_t offset); int processXRefStream(off_t offset, QPDFObjectHandle& xref_stream); - void insertXrefEntry(int obj, int f0, int f1, int f2); + void insertXrefEntry(int obj, int f0, int f1, int f2, + bool overwrite = false); QPDFObjectHandle readObject( InputSource*, int objid, int generation, bool in_object_stream); diff --git a/libqpdf/QPDF.cc b/libqpdf/QPDF.cc index 6f51fa2c..a90cddc2 100644 --- a/libqpdf/QPDF.cc +++ b/libqpdf/QPDF.cc @@ -435,7 +435,7 @@ QPDF::reconstruct_xref(QPDFExc& e) int obj = atoi(m.getMatch(1).c_str()); int gen = atoi(m.getMatch(2).c_str()); int offset = this->file.getLastOffset(); - insertXrefEntry(obj, 1, offset, gen); + insertXrefEntry(obj, 1, offset, gen, true); } else if ((! this->trailer.isInitialized()) && trailer_re.match(line.c_str())) @@ -865,11 +865,15 @@ QPDF::processXRefStream(off_t xref_offset, QPDFObjectHandle& xref_obj) } void -QPDF::insertXrefEntry(int obj, int f0, int f1, int f2) +QPDF::insertXrefEntry(int obj, int f0, int f1, int f2, bool overwrite) { // Populate the xref table in such a way that the first reference // to an object that we see, which is the one in the latest xref - // table in which it appears, is the one that gets stored. + // table in which it appears, is the one that gets stored. This + // works because we are reading more recent appends before older + // ones. Exception: if overwrite is true, then replace any + // existing object. This is used in xref recovery mode, which + // reads the file from beginning to end. // If there is already an entry for this object and generation in // 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) ObjGen og(obj, gen); if (this->xref_table.count(og)) { - QTC::TC("qpdf", "QPDF xref reused object"); - return; + if (overwrite) + { + QTC::TC("qpdf", "QPDF xref overwrite object"); + this->xref_table.erase(og); + } + else + { + QTC::TC("qpdf", "QPDF xref reused object"); + return; + } } if (this->deleted_objects.count(obj)) {