Commit a8f224872995e3b90297693cfe1f381f01c555c8

Authored by Jay Berkenbilt
1 parent 5ccc788b

handle files with object 0 as a real object

git-svn-id: svn+q:///qpdf/trunk@1049 71b93d88-0707-0410-a8cf-f5a4172ac649
ChangeLog
  1 +2011-01-31 Jay Berkenbilt <ejb@ql.org>
  2 +
  3 + * libqpdf/QPDF.cc (readObjectAtOffset): use -1 rather than 0 when
  4 + reading an object at a given to indicate that no object number is
  5 + expected. This allows xref recovery to proceed even if a file
  6 + uses the invalid object number 0 as a regular object.
  7 +
  8 + * libqpdf/QPDF_linearization.cc (isLinearized): use -1 rather than
  9 + 0 as a sentintel for not having found the first object in the
  10 + file. Since -1 can never match the regular expression, this
  11 + prevents an infinite loop when checking a file that starts with
  12 + (erroneous) 0 0 obj. (Fixes qpdf-Bugs-3159950.)
  13 +
1 2010-10-04 Jay Berkenbilt <ejb@ql.org> 14 2010-10-04 Jay Berkenbilt <ejb@ql.org>
2 15
3 * 2.2.2: release 16 * 2.2.2: release
libqpdf/QPDF.cc
@@ -782,7 +782,7 @@ QPDF::read_xrefStream(off_t xref_offset) @@ -782,7 +782,7 @@ QPDF::read_xrefStream(off_t xref_offset)
782 try 782 try
783 { 783 {
784 xref_obj = readObjectAtOffset( 784 xref_obj = readObjectAtOffset(
785 - false, xref_offset, "xref stream", 0, 0, xobj, xgen); 785 + false, xref_offset, "xref stream", -1, 0, xobj, xgen);
786 } 786 }
787 catch (QPDFExc& e) 787 catch (QPDFExc& e)
788 { 788 {
@@ -1580,7 +1580,7 @@ QPDF::readObjectAtOffset(bool try_recovery, @@ -1580,7 +1580,7 @@ QPDF::readObjectAtOffset(bool try_recovery,
1580 objid = atoi(tobjid.getValue().c_str()); 1580 objid = atoi(tobjid.getValue().c_str());
1581 generation = atoi(tgen.getValue().c_str()); 1581 generation = atoi(tgen.getValue().c_str());
1582 1582
1583 - if (exp_objid && 1583 + if ((exp_objid >= 0) &&
1584 (! ((objid == exp_objid) && (generation == exp_generation)))) 1584 (! ((objid == exp_objid) && (generation == exp_generation))))
1585 { 1585 {
1586 QTC::TC("qpdf", "QPDF err wrong objid/generation"); 1586 QTC::TC("qpdf", "QPDF err wrong objid/generation");
@@ -1593,7 +1593,7 @@ QPDF::readObjectAtOffset(bool try_recovery, @@ -1593,7 +1593,7 @@ QPDF::readObjectAtOffset(bool try_recovery,
1593 } 1593 }
1594 catch (QPDFExc& e) 1594 catch (QPDFExc& e)
1595 { 1595 {
1596 - if (exp_objid && try_recovery && this->attempt_recovery) 1596 + if ((exp_objid >= 0) && try_recovery && this->attempt_recovery)
1597 { 1597 {
1598 // Try again after reconstructing xref table 1598 // Try again after reconstructing xref table
1599 reconstruct_xref(e); 1599 reconstruct_xref(e);
libqpdf/QPDF_linearization.cc
@@ -95,9 +95,9 @@ QPDF::isLinearized() @@ -95,9 +95,9 @@ QPDF::isLinearized()
95 static PCRE lindict_re("(?s:(\\d+)\\s+0\\s+obj\\s*<<)"); 95 static PCRE lindict_re("(?s:(\\d+)\\s+0\\s+obj\\s*<<)");
96 96
97 off_t offset = -1; 97 off_t offset = -1;
98 - int lindict_obj = 0; 98 + int lindict_obj = -1;
99 char* p = buf; 99 char* p = buf;
100 - while (lindict_obj == 0) 100 + while (lindict_obj == -1)
101 { 101 {
102 PCRE::Match m(lindict_re.match(p)); 102 PCRE::Match m(lindict_re.match(p));
103 if (m) 103 if (m)
@@ -312,7 +312,7 @@ QPDF::readHintStream(Pipeline&amp; pl, off_t offset, size_t length) @@ -312,7 +312,7 @@ QPDF::readHintStream(Pipeline&amp; pl, off_t offset, size_t length)
312 int obj; 312 int obj;
313 int gen; 313 int gen;
314 QPDFObjectHandle H = readObjectAtOffset( 314 QPDFObjectHandle H = readObjectAtOffset(
315 - false, offset, "linearization hint stream", 0, 0, obj, gen); 315 + false, offset, "linearization hint stream", -1, 0, obj, gen);
316 ObjCache& oc = this->obj_cache[ObjGen(obj, gen)]; 316 ObjCache& oc = this->obj_cache[ObjGen(obj, gen)];
317 off_t min_end_offset = oc.end_before_space; 317 off_t min_end_offset = oc.end_before_space;
318 off_t max_end_offset = oc.end_after_space; 318 off_t max_end_offset = oc.end_after_space;
qpdf/qtest/qpdf.test
@@ -111,7 +111,7 @@ $td-&gt;runtest(&quot;new stream&quot;, @@ -111,7 +111,7 @@ $td-&gt;runtest(&quot;new stream&quot;,
111 show_ntests(); 111 show_ntests();
112 # ---------- 112 # ----------
113 $td->notify("--- Miscellaneous Tests ---"); 113 $td->notify("--- Miscellaneous Tests ---");
114 -$n_tests += 28; 114 +$n_tests += 29;
115 115
116 $td->runtest("qpdf version", 116 $td->runtest("qpdf version",
117 {$td->COMMAND => "qpdf --version"}, 117 {$td->COMMAND => "qpdf --version"},
@@ -191,6 +191,14 @@ foreach my $file (qw(short-id long-id)) @@ -191,6 +191,14 @@ foreach my $file (qw(short-id long-id))
191 $td->NORMALIZE_NEWLINES); 191 $td->NORMALIZE_NEWLINES);
192 } 192 }
193 193
  194 +# Handle file with invalid xref table and object 0 as a regular object
  195 +# (bug 3159950).
  196 +$td->runtest("check obj0.pdf",
  197 + {$td->COMMAND => "qpdf --check obj0.pdf"},
  198 + {$td->FILE => "obj0-check.out",
  199 + $td->EXIT_STATUS => 3},
  200 + $td->NORMALIZE_NEWLINES);
  201 +
194 # Min/Force version 202 # Min/Force version
195 $td->runtest("set min version", 203 $td->runtest("set min version",
196 {$td->COMMAND => "qpdf --min-version=1.6 good1.pdf a.pdf"}, 204 {$td->COMMAND => "qpdf --min-version=1.6 good1.pdf a.pdf"},
qpdf/qtest/qpdf/obj0-check.out 0 → 100644
  1 +checking obj0.pdf
  2 +PDF Version: 1.3
  3 +File is not encrypted
  4 +File is not linearized
  5 +WARNING: obj0.pdf: file is damaged
  6 +WARNING: obj0.pdf (object 1 0, file position 77): expected n n obj
  7 +WARNING: obj0.pdf: Attempting to reconstruct cross-reference table
qpdf/qtest/qpdf/obj0.pdf 0 → 100644
No preview for this file type