aboutsummaryrefslogtreecommitdiffstats
path: root/libqpdf
diff options
context:
space:
mode:
authorJay Berkenbilt <ejb@ql.org>2021-01-17 00:35:30 +0100
committerJay Berkenbilt <ejb@ql.org>2021-01-24 09:27:26 +0100
commitd61ffb65d034848157291b9825f4b33155bd55e7 (patch)
tree9eebcc0ab116bdf5e5d6fd80362c262d6fdc54f7 /libqpdf
parentba814703fbfc99c99d24c8873ae3356b2623dc69 (diff)
downloadqpdf-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.cc92
-rw-r--r--libqpdf/QPDFNameTreeObjectHelper.cc14
-rw-r--r--libqpdf/QPDFNumberTreeObjectHelper.cc14
-rw-r--r--libqpdf/qpdf/NNTree.hh7
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;
};