diff --git a/libqpdf/QPDF.cc b/libqpdf/QPDF.cc index fc0c103..d1360b1 100644 --- a/libqpdf/QPDF.cc +++ b/libqpdf/QPDF.cc @@ -917,6 +917,13 @@ QPDF::processXRefStream(qpdf_offset_t xref_offset, QPDFObjectHandle& xref_obj) } entry_size += W[i]; } + if (entry_size == 0) + { + throw QPDFExc(qpdf_e_damaged_pdf, this->file->getName(), + "xref stream", xref_offset, + "Cross-reference stream's /W indicates" + " entry size of 0"); + } long long max_num_entries = static_cast(-1) / entry_size; diff --git a/libqpdf/QPDFWriter.cc b/libqpdf/QPDFWriter.cc index 8ee322a..8d5f068 100644 --- a/libqpdf/QPDFWriter.cc +++ b/libqpdf/QPDFWriter.cc @@ -2056,6 +2056,10 @@ QPDFWriter::generateObjectStreams() std::vector const& eligible = QPDF::Writer::getCompressibleObjGens(this->pdf); unsigned int n_object_streams = (eligible.size() + 99) / 100; + if (n_object_streams == 0) + { + throw std::logic_error("n_object_streams == 0"); + } unsigned int n_per = eligible.size() / n_object_streams; if (n_per * n_object_streams < eligible.size()) { diff --git a/qpdf/qtest/qpdf.test b/qpdf/qtest/qpdf.test index 12fb5dd..89e41b3 100644 --- a/qpdf/qtest/qpdf.test +++ b/qpdf/qtest/qpdf.test @@ -218,6 +218,8 @@ my @bug_tests = ( ["119", "other infinite loop", 3], ["120", "other infinite loop", 3], ["106", "zlib data error", 3], + ["141a", "/W entry size 0", 2], + ["141b", "/W entry size 0", 2], ); $n_tests += scalar(@bug_tests); foreach my $d (@bug_tests) diff --git a/qpdf/qtest/qpdf/issue-141a.out b/qpdf/qtest/qpdf/issue-141a.out new file mode 100644 index 0000000..6182d90 --- /dev/null +++ b/qpdf/qtest/qpdf/issue-141a.out @@ -0,0 +1,8 @@ +WARNING: issue-141a.pdf: can't find PDF header +WARNING: issue-141a.pdf (xref stream: object 9 0, file position 10): stream dictionary lacks /Length key +WARNING: issue-141a.pdf (xref stream: object 9 0, file position 47): attempting to recover stream length +WARNING: issue-141a.pdf (xref stream: object 9 0, file position 47): unable to recover stream data; treating stream as empty +WARNING: issue-141a.pdf: file is damaged +WARNING: issue-141a.pdf (xref stream, file position 3): Cross-reference stream's /W indicates entry size of 0 +WARNING: issue-141a.pdf: Attempting to reconstruct cross-reference table +issue-141a.pdf: unable to find trailer dictionary while recovering damaged file diff --git a/qpdf/qtest/qpdf/issue-141a.pdf b/qpdf/qtest/qpdf/issue-141a.pdf new file mode 100644 index 0000000..dec76be --- /dev/null +++ b/qpdf/qtest/qpdf/issue-141a.pdf @@ -0,0 +1,6 @@ +0009 0 obj<>stream +endstream +endobj +startxref +3 +%%EOF diff --git a/qpdf/qtest/qpdf/issue-141b.out b/qpdf/qtest/qpdf/issue-141b.out new file mode 100644 index 0000000..bf59124 --- /dev/null +++ b/qpdf/qtest/qpdf/issue-141b.out @@ -0,0 +1,5 @@ +WARNING: issue-141b.pdf: can't find PDF header +WARNING: issue-141b.pdf: file is damaged +WARNING: issue-141b.pdf (file position 7): xref not found +WARNING: issue-141b.pdf: Attempting to reconstruct cross-reference table +issue-141b.pdf: unable to find trailer dictionary while recovering damaged file diff --git a/qpdf/qtest/qpdf/issue-141b.pdf b/qpdf/qtest/qpdf/issue-141b.pdf new file mode 100644 index 0000000..67ce5ab --- /dev/null +++ b/qpdf/qtest/qpdf/issue-141b.pdf @@ -0,0 +1,6 @@ +%PDF-100 0 obj<>stream +0endstream +endobj +startxref +7 +%%EOF \ No newline at end of file