diff options
author | Jay Berkenbilt <ejb@ql.org> | 2021-01-17 00:35:30 +0100 |
---|---|---|
committer | Jay Berkenbilt <ejb@ql.org> | 2021-01-24 09:27:26 +0100 |
commit | d61ffb65d034848157291b9825f4b33155bd55e7 (patch) | |
tree | 9eebcc0ab116bdf5e5d6fd80362c262d6fdc54f7 /libqpdf | |
parent | ba814703fbfc99c99d24c8873ae3356b2623dc69 (diff) | |
download | qpdf-d61ffb65d034848157291b9825f4b33155bd55e7.tar.zst |
Add new constructors for name/number tree helpers
Add constructors that take a QPDF object so we can issue warnings and
create new indirect objects.
Diffstat (limited to 'libqpdf')
-rw-r--r-- | libqpdf/NNTree.cc | 92 | ||||
-rw-r--r-- | libqpdf/QPDFNameTreeObjectHelper.cc | 14 | ||||
-rw-r--r-- | libqpdf/QPDFNumberTreeObjectHelper.cc | 14 | ||||
-rw-r--r-- | libqpdf/qpdf/NNTree.hh | 7 |
4 files changed, 103 insertions, 24 deletions
diff --git a/libqpdf/NNTree.cc b/libqpdf/NNTree.cc index abc0043b..be7a1d4d 100644 --- a/libqpdf/NNTree.cc +++ b/libqpdf/NNTree.cc @@ -1,8 +1,49 @@ #include <qpdf/NNTree.hh> +#include <qpdf/QTC.hh> #include <qpdf/QUtil.hh> #include <exception> +static std::string +get_description(QPDFObjectHandle& node) +{ + std::string result("Name/Number tree node"); + if (node.isIndirect()) + { + result += " (object " + QUtil::int_to_string(node.getObjectID()) + ")"; + } + return result; +} + +static void +warn(QPDF* qpdf, QPDFObjectHandle& node, std::string const& msg) +{ + // ABI: in qpdf 11, change to a reference. + + if (qpdf) + { + qpdf->warn(QPDFExc( + qpdf_e_damaged_pdf, + qpdf->getFilename(), get_description(node), 0, msg)); + } +} + +static void +error(QPDF* qpdf, QPDFObjectHandle& node, std::string const& msg) +{ + // ABI: in qpdf 11, change to a reference. + + if (qpdf) + { + throw QPDFExc(qpdf_e_damaged_pdf, + qpdf->getFilename(), get_description(node), 0, msg); + } + else + { + throw std::runtime_error(get_description(node) + ": " + msg); + } +} + NNTreeIterator::PathElement::PathElement( QPDFObjectHandle const& node, int kid_number) : node(node), @@ -138,6 +179,13 @@ NNTreeIterator::addPathElement(QPDFObjectHandle const& node, } void +NNTreeIterator::reset() +{ + this->path.clear(); + this->item_number = -1; +} + +void NNTreeIterator::deepen(QPDFObjectHandle node, bool first) { std::set<QPDFObjGen> seen; @@ -148,7 +196,11 @@ NNTreeIterator::deepen(QPDFObjectHandle node, bool first) auto og = node.getObjGen(); if (seen.count(og)) { - throw std::runtime_error("loop detected"); + QTC::TC("qpdf", "NNTree deepen: loop"); + warn(qpdf, node, + "loop detected while traversing name/number tree"); + reset(); + return; } seen.insert(og); } @@ -169,7 +221,11 @@ NNTreeIterator::deepen(QPDFObjectHandle node, bool first) } else { - throw std::runtime_error("node has neither /Kids nor /Names"); + QTC::TC("qpdf", "NNTree deepen: invalid node"); + warn(qpdf, node, + "name/number tree node has neither /Kids nor /Names"); + reset(); + return; } } } @@ -179,6 +235,7 @@ NNTreeImpl::NNTreeImpl(NNTreeDetails const& details, QPDFObjectHandle& oh, bool auto_repair) : details(details), + qpdf(qpdf), oh(oh) { } @@ -186,7 +243,7 @@ NNTreeImpl::NNTreeImpl(NNTreeDetails const& details, NNTreeImpl::iterator NNTreeImpl::begin() { - iterator result(details); + iterator result(details, this->qpdf); result.deepen(this->oh, true); return result; } @@ -194,13 +251,13 @@ NNTreeImpl::begin() NNTreeImpl::iterator NNTreeImpl::end() { - return iterator(details); + return iterator(details, this->qpdf); } NNTreeImpl::iterator NNTreeImpl::last() { - iterator result(details); + iterator result(details, this->qpdf); result.deepen(this->oh, false); return result; } @@ -315,21 +372,22 @@ NNTreeImpl::compareKeyItem( if (! ((items.isArray() && (items.getArrayNItems() > (2 * idx)) && details.keyValid(items.getArrayItem(2 * idx))))) { - throw std::runtime_error("item at index " + - QUtil::int_to_string(2 * idx) + - " is not the right type"); + error(qpdf, this->oh, + "item at index " + QUtil::int_to_string(2 * idx) + + " is not the right type"); } return details.compareKeys(key, items.getArrayItem(2 * idx)); } int -NNTreeImpl::compareKeyKid(QPDFObjectHandle& key, QPDFObjectHandle& kids, int idx) +NNTreeImpl::compareKeyKid( + QPDFObjectHandle& key, QPDFObjectHandle& kids, int idx) { if (! (kids.isArray() && (idx < kids.getArrayNItems()) && kids.getArrayItem(idx).isDictionary())) { - throw std::runtime_error("invalid kid at index " + - QUtil::int_to_string(idx)); + error(qpdf, this->oh, + "invalid kid at index " + QUtil::int_to_string(idx)); } return withinLimits(key, kids.getArrayItem(idx)); } @@ -364,14 +422,14 @@ NNTreeImpl::find(QPDFObjectHandle key, bool return_prev_if_not_found) std::set<QPDFObjGen> seen; auto node = this->oh; - iterator result(details); + iterator result(details, this->qpdf); while (true) { auto og = node.getObjGen(); if (seen.count(og)) { - throw std::runtime_error("loop detected in find"); + error(qpdf, node, "loop detected in find"); } seen.insert(og); @@ -397,16 +455,16 @@ NNTreeImpl::find(QPDFObjectHandle key, bool return_prev_if_not_found) &NNTreeImpl::compareKeyKid); if (idx == -1) { - throw std::runtime_error( - "unexpected -1 from binary search of kids;" - " tree may not be sorted"); + error(qpdf, node, + "unexpected -1 from binary search of kids;" + " tree may not be sorted"); } result.addPathElement(node, idx); node = kids.getArrayItem(idx); } else { - throw std::runtime_error("bad node during find"); + error(qpdf, node, "bad node during find"); } } diff --git a/libqpdf/QPDFNameTreeObjectHelper.cc b/libqpdf/QPDFNameTreeObjectHelper.cc index f7576e94..526de2e6 100644 --- a/libqpdf/QPDFNameTreeObjectHelper.cc +++ b/libqpdf/QPDFNameTreeObjectHelper.cc @@ -33,14 +33,22 @@ QPDFNameTreeObjectHelper::Members::~Members() { } -QPDFNameTreeObjectHelper::Members::Members(QPDFObjectHandle& oh) : - impl(std::make_shared<NNTreeImpl>(name_tree_details, nullptr, oh, false)) +QPDFNameTreeObjectHelper::Members::Members( + QPDFObjectHandle& oh, QPDF* q, bool auto_repair) : + impl(std::make_shared<NNTreeImpl>(name_tree_details, q, oh, auto_repair)) +{ +} + +QPDFNameTreeObjectHelper::QPDFNameTreeObjectHelper( + QPDFObjectHandle oh, QPDF& q, bool auto_repair) : + QPDFObjectHelper(oh), + m(new Members(oh, &q, auto_repair)) { } QPDFNameTreeObjectHelper::QPDFNameTreeObjectHelper(QPDFObjectHandle oh) : QPDFObjectHelper(oh), - m(new Members(oh)) + m(new Members(oh, nullptr, false)) { } diff --git a/libqpdf/QPDFNumberTreeObjectHelper.cc b/libqpdf/QPDFNumberTreeObjectHelper.cc index 6371287f..b31895cd 100644 --- a/libqpdf/QPDFNumberTreeObjectHelper.cc +++ b/libqpdf/QPDFNumberTreeObjectHelper.cc @@ -33,14 +33,22 @@ QPDFNumberTreeObjectHelper::Members::~Members() { } -QPDFNumberTreeObjectHelper::Members::Members(QPDFObjectHandle& oh) : - impl(std::make_shared<NNTreeImpl>(number_tree_details, nullptr, oh, false)) +QPDFNumberTreeObjectHelper::Members::Members( + QPDFObjectHandle& oh, QPDF* q, bool auto_repair) : + impl(std::make_shared<NNTreeImpl>(number_tree_details, q, oh, auto_repair)) +{ +} + +QPDFNumberTreeObjectHelper::QPDFNumberTreeObjectHelper( + QPDFObjectHandle oh, QPDF& q, bool auto_repair) : + QPDFObjectHelper(oh), + m(new Members(oh, &q, auto_repair)) { } QPDFNumberTreeObjectHelper::QPDFNumberTreeObjectHelper(QPDFObjectHandle oh) : QPDFObjectHelper(oh), - m(new Members(oh)) + m(new Members(oh, nullptr, false)) { } diff --git a/libqpdf/qpdf/NNTree.hh b/libqpdf/qpdf/NNTree.hh index 910fb225..07bd871b 100644 --- a/libqpdf/qpdf/NNTree.hh +++ b/libqpdf/qpdf/NNTree.hh @@ -57,17 +57,21 @@ class NNTreeIterator: public std::iterator< int kid_number; }; - NNTreeIterator(NNTreeDetails const& details) : + // ABI: for qpdf 11, make qpdf a reference + NNTreeIterator(NNTreeDetails const& details, QPDF* qpdf) : details(details), + qpdf(qpdf), item_number(-1) { } + void reset(); void deepen(QPDFObjectHandle node, bool first); void setItemNumber(QPDFObjectHandle const& node, int); void addPathElement(QPDFObjectHandle const& node, int kid_number); void increment(bool backward); NNTreeDetails const& details; + QPDF* qpdf; std::list<PathElement> path; QPDFObjectHandle node; int item_number; @@ -99,6 +103,7 @@ class NNTreeImpl QPDFObjectHandle& key, QPDFObjectHandle& items, int idx); NNTreeDetails const& details; + QPDF* qpdf; QPDFObjectHandle oh; }; |