diff --git a/ChangeLog b/ChangeLog index 510c6145..bd0acc2b 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,8 @@ +2017-08-25 Jay Berkenbilt + + * Detect infinite loop while finding additional xref tables. Fixes + #149. + 2017-08-22 Jay Berkenbilt * 7.0.b1: release diff --git a/libqpdf/QPDF.cc b/libqpdf/QPDF.cc index 27efdd55..86e798ee 100644 --- a/libqpdf/QPDF.cc +++ b/libqpdf/QPDF.cc @@ -491,8 +491,10 @@ void QPDF::read_xref(qpdf_offset_t xref_offset) { std::map free_table; + std::set visited; while (xref_offset) { + visited.insert(xref_offset); char buf[7]; memset(buf, 0, sizeof(buf)); this->m->file->seek(xref_offset, SEEK_SET); @@ -520,6 +522,10 @@ QPDF::read_xref(qpdf_offset_t xref_offset) { xref_offset = read_xrefStream(xref_offset); } + if (visited.count(xref_offset) != 0) + { + xref_offset = 0; + } } if (! this->m->trailer.isInitialized()) diff --git a/qpdf/qtest/qpdf.test b/qpdf/qtest/qpdf.test index 232e421e..9ecf0005 100644 --- a/qpdf/qtest/qpdf.test +++ b/qpdf/qtest/qpdf.test @@ -221,6 +221,7 @@ my @bug_tests = ( ["141a", "/W entry size 0", 2], ["141b", "/W entry size 0", 2], ["143", "self-referential ostream", 3], + ["149", "xref prev pointer loop", 3], ); $n_tests += scalar(@bug_tests); foreach my $d (@bug_tests) diff --git a/qpdf/qtest/qpdf/issue-149.out b/qpdf/qtest/qpdf/issue-149.out new file mode 100644 index 00000000..5c473389 --- /dev/null +++ b/qpdf/qtest/qpdf/issue-149.out @@ -0,0 +1,2 @@ +WARNING: issue-149.pdf: reported number of objects (11) inconsistent with actual number of objects (7) +qpdf: operation succeeded with warnings; resulting file may have some problems diff --git a/qpdf/qtest/qpdf/issue-149.pdf b/qpdf/qtest/qpdf/issue-149.pdf new file mode 100644 index 00000000..9a2f8a88 --- /dev/null +++ b/qpdf/qtest/qpdf/issue-149.pdf @@ -0,0 +1,120 @@ +%PDF-1.7 +%Á∑·∂ +% vim: set tw=76 ts=2 et : +% convert with: +% ./fixlengths < hello.txt > hello.pdf ; ./genxref hello.pdf +1 0 obj + << /Type /Catalog + /Outlines 6 0 R + /Pages 2 0 R + >> +endobj + +2 0 obj + << /Type /Pages + /Kids [3 0 R] + /Count 1 + >> +endobj + +3 0 obj + << /Type /Page + /Parent 2 0 R + /MediaBox [0 0 595.276 841.89] + /Contents 4 0 R + /Resources << + /ProcSet [/PDF /Text] + /Font << /F1 5 0 R >> + >> + >> +endobj + +4 0 obj + << /Length 36 >> +stream + BT 80 100 Td /F1 48 Tf (foo) Tj ET +endstream +endobj + +5 0 obj + << /Type /Font + /Subtype /Type1 + /Name /F1 + /BaseFont /Helvetica + /Encoding /MacRomanEncoding + >> +endobj + +6 0 obj + << /Type /Outlines + /Count 0 + >> +endobj + +xref +0 7 +0000000000 65535 f +0000000125 00000 n +0000000208 00000 n +0000000283 00000 n +0000000492 00000 n +0000000583 00000 n +0000000721 00000 n + +trailer + << /Size 7 + /Prev 1516 + /Root 1 0 R + >> +startxref +779%%EOF + +% %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +1 1 obj + << /Type /Catalog + /Outlines 6 0 R + /Pages 2 1 R + >> +endobj + +2 1 obj + << /Type /Pages + /Kids [3 1 R] + /Count 1 + >> +endobj + +3 1 obj + << /Type /Page + /Parent 2 1 R + /MediaBox [0 0 595.276 841.89] + /Contents 4 1 R + /Resources << + /ProcSet [/PDF /Text] + /Font << /F1 5 0 R >> + >> + >> +endobj + +4 1 obj + << /Length 36 >> +stream + BT 80 100 Td /F1 48 Tf (bar) Tj ET +endstream +endobj + +xref +1 4 +0000001058 00001 n +0000001141 00001 n +0000001216 00001 n +0000001425 00001 n + +trailer + << /Size 11 + /Prev 779 + /Root 1 1 R + >> +startxref +1516 +%%EOF