From a4db9b3149562a6117b1d9edf89e3853480aeba8 Mon Sep 17 00:00:00 2001 From: m-holger Date: Sat, 10 Aug 2024 12:40:59 +0100 Subject: [PATCH] Move QPDF::read_xref to QPDF::Xref_table --- include/qpdf/QPDF.hh | 1 - libqpdf/QPDF.cc | 43 +++++++++++++++++++++---------------------- libqpdf/qpdf/QPDF_private.hh | 10 +++++++--- 3 files changed, 28 insertions(+), 26 deletions(-) diff --git a/include/qpdf/QPDF.hh b/include/qpdf/QPDF.hh index d8f3869..5e0b96d 100644 --- a/include/qpdf/QPDF.hh +++ b/include/qpdf/QPDF.hh @@ -759,7 +759,6 @@ class QPDF void parse(char const* password); void inParse(bool); - void read_xref(qpdf_offset_t offset); bool resolveXRefTable(); void setLastObjectDescription(std::string const& description, QPDFObjGen const& og); QPDFObjectHandle readTrailer(); diff --git a/libqpdf/QPDF.cc b/libqpdf/QPDF.cc index e5c9940..fd8c736 100644 --- a/libqpdf/QPDF.cc +++ b/libqpdf/QPDF.cc @@ -468,7 +468,7 @@ QPDF::parse(char const* password) throw damagedPDF("", 0, "can't find startxref"); } try { - read_xref(xref_offset); + m->xref_table.read(xref_offset); } catch (QPDFExc&) { throw; } catch (std::exception& e) { @@ -625,7 +625,7 @@ QPDF::Xref_table::reconstruct(QPDFExc& e) } if (max_offset > 0) { try { - qpdf.read_xref(max_offset); + read(max_offset); } catch (std::exception&) { throw damaged_pdf( "error decoding candidate xref stream while recovering damaged file"); @@ -664,8 +664,10 @@ QPDF::Xref_table::reconstruct(QPDFExc& e) } void -QPDF::read_xref(qpdf_offset_t xref_offset) +QPDF::Xref_table::read(qpdf_offset_t xref_offset) { + auto* m = qpdf.m.get(); + std::map free_table; std::set visited; while (xref_offset) { @@ -700,7 +702,7 @@ QPDF::read_xref(qpdf_offset_t xref_offset) if ((strncmp(buf, "xref", 4) == 0) && QUtil::is_space(buf[4])) { if (skipped_space) { QTC::TC("qpdf", "QPDF xref skipped space"); - warn(damagedPDF("", 0, "extraneous whitespace seen before xref")); + warn_damaged("extraneous whitespace seen before xref"); } QTC::TC( "qpdf", @@ -714,46 +716,43 @@ QPDF::read_xref(qpdf_offset_t xref_offset) while (QUtil::is_space(buf[skip])) { ++skip; } - xref_offset = m->xref_table.read_table(xref_offset + skip); + xref_offset = read_table(xref_offset + skip); } else { - xref_offset = m->xref_table.read_stream(xref_offset); + xref_offset = read_stream(xref_offset); } if (visited.count(xref_offset) != 0) { QTC::TC("qpdf", "QPDF xref loop"); - throw damagedPDF("", 0, "loop detected following xref tables"); + throw damaged_pdf("loop detected following xref tables"); } } - if (!m->xref_table.trailer) { - throw damagedPDF("", 0, "unable to find trailer while reading xref"); + if (!trailer) { + throw damaged_pdf("unable to find trailer while reading xref"); } - int size = m->xref_table.trailer.getKey("/Size").getIntValueAsInt(); + int size = trailer.getKey("/Size").getIntValueAsInt(); int max_obj = 0; - if (!m->xref_table.empty()) { - max_obj = m->xref_table.rbegin()->first.getObj(); + if (!empty()) { + max_obj = rbegin()->first.getObj(); } - if (!m->xref_table.deleted_objects.empty()) { - max_obj = std::max(max_obj, *(m->xref_table.deleted_objects.rbegin())); + if (!deleted_objects.empty()) { + max_obj = std::max(max_obj, *deleted_objects.rbegin()); } if ((size < 1) || (size - 1 != max_obj)) { QTC::TC("qpdf", "QPDF xref size mismatch"); - warn(damagedPDF( - "", - 0, - ("reported number of objects (" + std::to_string(size) + - ") is not one plus the highest object number (" + std::to_string(max_obj) + ")"))); + warn_damaged("reported number of objects (" + std::to_string(size) + + ") is not one plus the highest object number (" + std::to_string(max_obj) + ")"); } // We no longer need the deleted_objects table, so go ahead and clear it out to make sure we // never depend on its being set. - m->xref_table.deleted_objects.clear(); + deleted_objects.clear(); // Make sure we keep only the highest generation for any object. QPDFObjGen last_og{-1, 0}; - for (auto const& item: m->xref_table) { + for (auto const& item: *this) { auto id = item.first.getObj(); if (id == last_og.getObj() && id > 0) { - removeObject(last_og); + qpdf.removeObject(last_og); } last_og = item.first; } diff --git a/libqpdf/qpdf/QPDF_private.hh b/libqpdf/qpdf/QPDF_private.hh index df35bee..63aecc7 100644 --- a/libqpdf/qpdf/QPDF_private.hh +++ b/libqpdf/qpdf/QPDF_private.hh @@ -12,9 +12,7 @@ class QPDF::Xref_table: public std::map { } - qpdf_offset_t read_table(qpdf_offset_t offset); - qpdf_offset_t read_stream(qpdf_offset_t offset); - + void read(qpdf_offset_t offset); void reconstruct(QPDFExc& e); QPDFObjectHandle trailer; @@ -32,9 +30,14 @@ class QPDF::Xref_table: public std::map qpdf_offset_t first_item_offset{0}; // actual value from file private: + // Methods to parse tables + qpdf_offset_t read_table(qpdf_offset_t offset); bool parse_first(std::string const& line, int& obj, int& num, int& bytes); bool read_entry(qpdf_offset_t& f1, int& f2, char& type); bool read_bad_entry(qpdf_offset_t& f1, int& f2, char& type); + + // Methods to parse streams + qpdf_offset_t read_stream(qpdf_offset_t offset); qpdf_offset_t process_stream(qpdf_offset_t offset, QPDFObjectHandle& xref_stream); std::pair> process_W(QPDFObjectHandle& dict, std::function damaged); @@ -45,6 +48,7 @@ class QPDF::Xref_table: public std::map int max_num_entries, std::function damaged); + // Methods to insert table entries void insert_reconstructed(int obj, qpdf_offset_t f1, int f2); void insert(int obj, int f0, qpdf_offset_t f1, int f2); void insert_free(QPDFObjGen); -- libgit2 0.21.4