From e28625144d8eb77b98d3e64107aa0f353863def4 Mon Sep 17 00:00:00 2001 From: m-holger Date: Mon, 8 Jan 2024 13:42:05 +0000 Subject: [PATCH] Tweak QPDF::getCompressibleObjGens --- libqpdf/QPDF.cc | 19 ++++++++++++------- 1 file changed, 12 insertions(+), 7 deletions(-) diff --git a/libqpdf/QPDF.cc b/libqpdf/QPDF.cc index e2371c9d..89d4a0a8 100644 --- a/libqpdf/QPDF.cc +++ b/libqpdf/QPDF.cc @@ -2398,7 +2398,6 @@ QPDF::getCompressibleObjGens() const size_t max_obj = getObjectCount(); std::vector visited(max_obj, false); - QPDFObjGen::set visited_gen; // for objects with generation > 0 std::vector queue; queue.reserve(512); queue.push_back(m->trailer); @@ -2409,19 +2408,25 @@ QPDF::getCompressibleObjGens() if (obj.isIndirect()) { QPDFObjGen og = obj.getObjGen(); const size_t id = toS(og.getObj() - 1); - const int gen = og.getGen(); if (id >= max_obj) throw std::logic_error( "unexpected object id encountered in getCompressibleObjGens"); - if ((gen == 0 && visited[id]) || visited_gen.count(og)) { + if (visited[id]) { QTC::TC("qpdf", "QPDF loop detected traversing objects"); continue; } - if (gen == 0) { - visited[id] = true; - } else { - visited_gen.insert(og); + + // Check whether this is the current object. If not, remove it (which changes it into a + // direct null and therefore stops us from revisiting it) and move on to the next object + // in the queue. + auto upper = m->obj_cache.upper_bound(og); + if (upper != m->obj_cache.end() && upper->first.getObj() == og.getObj()) { + removeObject(og); + continue; } + + visited[id] = true; + if (og == encryption_dict_og) { QTC::TC("qpdf", "QPDF exclude encryption dictionary"); } else if (!(obj.isStream() ||