Commit 46611f0710fa08f1a90134a84cfccec3a1e49f94

Authored by Jay Berkenbilt
1 parent 8fe0b06c

Prevent a division by zero error (fixes #141)

Bad /W in an xref stream could cause a division by zero error. Now
this is handled as a special case.
libqpdf/QPDF.cc
... ... @@ -917,6 +917,13 @@ QPDF::processXRefStream(qpdf_offset_t xref_offset, QPDFObjectHandle& xref_obj)
917 917 }
918 918 entry_size += W[i];
919 919 }
  920 + if (entry_size == 0)
  921 + {
  922 + throw QPDFExc(qpdf_e_damaged_pdf, this->file->getName(),
  923 + "xref stream", xref_offset,
  924 + "Cross-reference stream's /W indicates"
  925 + " entry size of 0");
  926 + }
920 927 long long max_num_entries =
921 928 static_cast<unsigned long long>(-1) / entry_size;
922 929  
... ...
libqpdf/QPDFWriter.cc
... ... @@ -2056,6 +2056,10 @@ QPDFWriter::generateObjectStreams()
2056 2056 std::vector<QPDFObjGen> const& eligible =
2057 2057 QPDF::Writer::getCompressibleObjGens(this->pdf);
2058 2058 unsigned int n_object_streams = (eligible.size() + 99) / 100;
  2059 + if (n_object_streams == 0)
  2060 + {
  2061 + throw std::logic_error("n_object_streams == 0");
  2062 + }
2059 2063 unsigned int n_per = eligible.size() / n_object_streams;
2060 2064 if (n_per * n_object_streams < eligible.size())
2061 2065 {
... ...
qpdf/qtest/qpdf.test
... ... @@ -218,6 +218,8 @@ my @bug_tests = (
218 218 ["119", "other infinite loop", 3],
219 219 ["120", "other infinite loop", 3],
220 220 ["106", "zlib data error", 3],
  221 + ["141a", "/W entry size 0", 2],
  222 + ["141b", "/W entry size 0", 2],
221 223 );
222 224 $n_tests += scalar(@bug_tests);
223 225 foreach my $d (@bug_tests)
... ...
qpdf/qtest/qpdf/issue-141a.out 0 → 100644
  1 +WARNING: issue-141a.pdf: can't find PDF header
  2 +WARNING: issue-141a.pdf (xref stream: object 9 0, file position 10): stream dictionary lacks /Length key
  3 +WARNING: issue-141a.pdf (xref stream: object 9 0, file position 47): attempting to recover stream length
  4 +WARNING: issue-141a.pdf (xref stream: object 9 0, file position 47): unable to recover stream data; treating stream as empty
  5 +WARNING: issue-141a.pdf: file is damaged
  6 +WARNING: issue-141a.pdf (xref stream, file position 3): Cross-reference stream's /W indicates entry size of 0
  7 +WARNING: issue-141a.pdf: Attempting to reconstruct cross-reference table
  8 +issue-141a.pdf: unable to find trailer dictionary while recovering damaged file
... ...
qpdf/qtest/qpdf/issue-141a.pdf 0 → 100644
  1 +0009 0 obj<</Type/XRef/Size 0/W[0 0 0]>>stream
  2 +endstream
  3 +endobj
  4 +startxref
  5 +3
  6 +%%EOF
... ...
qpdf/qtest/qpdf/issue-141b.out 0 → 100644
  1 +WARNING: issue-141b.pdf: can't find PDF header
  2 +WARNING: issue-141b.pdf: file is damaged
  3 +WARNING: issue-141b.pdf (file position 7): xref not found
  4 +WARNING: issue-141b.pdf: Attempting to reconstruct cross-reference table
  5 +issue-141b.pdf: unable to find trailer dictionary while recovering damaged file
... ...
qpdf/qtest/qpdf/issue-141b.pdf 0 → 100644
  1 +%PDF-100 0 obj<</Type/XRef/Size 0/[]/W[0 0 0]/ 0>>stream
  2 +0endstream
  3 +endobj
  4 +startxref
  5 +7
  6 +%%EOF
0 7 \ No newline at end of file
... ...