Commit 02e89bbe47853a59f40de27e997dbdb67712586b
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.
Showing
5 changed files
with
27 additions
and
25 deletions
fuzz/CMakeLists.txt
fuzz/qpdf_extra/68668.fuzz
0 → 100644
No preview for this file type
fuzz/qtest/fuzz.test
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 | ... | ... |