Commit 02e89bbe47853a59f40de27e997dbdb67712586b

Authored by m-holger
1 parent 6ae439f1

Fix bug in QPDFWriter::preserveObjectStreams

Code failed to allow for QPDF::getCompressibleObjSet deleting objects
from the object cache in case of multiple entries for the same object id.

Add fuzz test case 68668.
fuzz/CMakeLists.txt
... ... @@ -116,6 +116,7 @@ set(CORPUS_OTHER
116 116 65777.fuzz
117 117 68374.fuzz
118 118 68377.fuzz
  119 + 68668.fuzz
119 120 )
120 121  
121 122 set(CORPUS_DIR ${CMAKE_CURRENT_BINARY_DIR}/qpdf_corpus)
... ...
fuzz/qpdf_extra/68668.fuzz 0 → 100644
No preview for this file type
fuzz/qtest/fuzz.test
... ... @@ -21,7 +21,7 @@ my @fuzzers = (
21 21 ['pngpredictor' => 1],
22 22 ['runlength' => 6],
23 23 ['tiffpredictor' => 2],
24   - ['qpdf' => 58], # increment when adding new files
  24 + ['qpdf' => 59], # increment when adding new files
25 25 );
26 26  
27 27 my $n_tests = 0;
... ...
libqpdf/QPDFWriter.cc
... ... @@ -1944,28 +1944,30 @@ QPDFWriter::preserveObjectStreams()
1944 1944 // that are not allowed to be in object streams. In addition to removing objects that were
1945 1945 // erroneously included in object streams in the source PDF, it also prevents unreferenced
1946 1946 // objects from being included.
1947   - auto iter = xref.cbegin();
1948 1947 auto end = xref.cend();
1949   -
1950   - // Start by scanning for first compressed object in case we don't have any object streams to
1951   - // process.
1952   - for (; iter != end; ++iter) {
1953   - if (iter->second.getType() == 2) {
1954   - // Pdf contains object streams.
1955   - QTC::TC(
1956   - "qpdf",
1957   - "QPDFWriter preserve object streams",
1958   - m->preserve_unreferenced_objects ? 0 : 1);
1959   -
1960   - if (m->preserve_unreferenced_objects) {
1961   - for (; iter != end; ++iter) {
1962   - if (iter->second.getType() == 2) {
1963   - m->obj[iter->first].object_stream = iter->second.getObjStreamNumber();
1964   - }
1965   - }
1966   - } else {
  1948 + m->obj.streams_empty = true;
  1949 + if (m->preserve_unreferenced_objects) {
  1950 + for (auto iter = xref.cbegin(); iter != end; ++iter) {
  1951 + if (iter->second.getType() == 2) {
  1952 + // Pdf contains object streams.
  1953 + QTC::TC("qpdf", "QPDFWriter preserve object streams preserve unreferenced");
  1954 + m->obj.streams_empty = false;
  1955 + m->obj[iter->first].object_stream = iter->second.getObjStreamNumber();
  1956 + }
  1957 + }
  1958 + } else {
  1959 + // Start by scanning for first compressed object in case we don't have any object streams to
  1960 + // process.
  1961 + for (auto iter = xref.cbegin(); iter != end; ++iter) {
  1962 + if (iter->second.getType() == 2) {
  1963 + // Pdf contains object streams.
  1964 + QTC::TC("qpdf", "QPDFWriter preserve object streams");
  1965 + m->obj.streams_empty = false;
1967 1966 auto eligible = QPDF::Writer::getCompressibleObjSet(m->pdf);
1968   - for (; iter != end; ++iter) {
  1967 + // The object pointed to by iter may be a previous generation, in which case it is
  1968 + // removed by getCompressibleObjSet. We need to restart the loop (while the object
  1969 + // table may contain multiple generations of an object).
  1970 + for (iter = xref.cbegin(); iter != end; ++iter) {
1969 1971 if (iter->second.getType() == 2) {
1970 1972 auto id = static_cast<size_t>(iter->first.getObj());
1971 1973 if (id < eligible.size() && eligible[id]) {
... ... @@ -1975,12 +1977,10 @@ QPDFWriter::preserveObjectStreams()
1975 1977 }
1976 1978 }
1977 1979 }
  1980 + return;
1978 1981 }
1979   - return;
1980 1982 }
1981 1983 }
1982   - // No compressed objects found.
1983   - m->obj.streams_empty = true;
1984 1984 }
1985 1985  
1986 1986 void
... ...
qpdf/qpdf.testcov
... ... @@ -600,7 +600,8 @@ QPDFAcroFormDocumentHelper AP parse error 0
600 600 QPDFJob copy fields not this file 0
601 601 QPDFJob copy fields non-first from orig 0
602 602 QPDF resolve duplicated page in insert 0
603   -QPDFWriter preserve object streams 1
  603 +QPDFWriter preserve object streams 0
  604 +QPDFWriter preserve object streams preserve unreferenced 0
604 605 QPDFWriter exclude from object stream 0
605 606 QPDF_pages findPage not found 0
606 607 QPDFObjectHandle check ownership 0
... ...