aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--ChangeLog5
-rw-r--r--TODO1
-rw-r--r--fuzz/qpdf_extra/23172.fuzzbin0 -> 26638 bytes
-rw-r--r--include/qpdf/QPDF.hh3
-rw-r--r--libqpdf/QPDF_optimization.cc17
5 files changed, 17 insertions, 9 deletions
diff --git a/ChangeLog b/ChangeLog
index 4a59b6a7..b217b8f3 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,8 @@
+2020-10-22 Jay Berkenbilt <ejb@ql.org>
+
+ * Fix loop detection problem when traversing page thumbnails
+ during optimization (fuzz issue 23172).
+
2020-10-21 Jay Berkenbilt <ejb@ql.org>
* Bug fix: properly handle copying foreign streams that have
diff --git a/TODO b/TODO
index 3f4e0976..a2854a2e 100644
--- a/TODO
+++ b/TODO
@@ -65,7 +65,6 @@ Fuzz Errors
* https://bugs.chromium.org/p/oss-fuzz/issues/detail?id=<N>
* New:
- * 23172: stack overflow (https://oss-fuzz.com/testcase-detail/5719543787028480)
* 23599: integer overflow: https://oss-fuzz.com/testcase?key=6290807920525312
* 23642: leak: https://oss-fuzz.com/testcase-detail/4906569690251264
diff --git a/fuzz/qpdf_extra/23172.fuzz b/fuzz/qpdf_extra/23172.fuzz
new file mode 100644
index 00000000..802711cb
--- /dev/null
+++ b/fuzz/qpdf_extra/23172.fuzz
Binary files differ
diff --git a/include/qpdf/QPDF.hh b/include/qpdf/QPDF.hh
index 720c1bc8..2482b232 100644
--- a/include/qpdf/QPDF.hh
+++ b/include/qpdf/QPDF.hh
@@ -1341,7 +1341,8 @@ class QPDF
std::set<QPDFObjGen>& visited);
void updateObjectMaps(ObjUser const& ou, QPDFObjectHandle oh);
void updateObjectMapsInternal(ObjUser const& ou, QPDFObjectHandle oh,
- std::set<QPDFObjGen>& visited, bool top);
+ std::set<QPDFObjGen>& visited, bool top,
+ int depth);
void filterCompressedObjects(std::map<int, int> const& object_stream_data);
// Type conversion helper methods
diff --git a/libqpdf/QPDF_optimization.cc b/libqpdf/QPDF_optimization.cc
index afa7ccbd..05cac415 100644
--- a/libqpdf/QPDF_optimization.cc
+++ b/libqpdf/QPDF_optimization.cc
@@ -354,12 +354,13 @@ void
QPDF::updateObjectMaps(ObjUser const& ou, QPDFObjectHandle oh)
{
std::set<QPDFObjGen> visited;
- updateObjectMapsInternal(ou, oh, visited, true);
+ updateObjectMapsInternal(ou, oh, visited, true, 0);
}
void
QPDF::updateObjectMapsInternal(ObjUser const& ou, QPDFObjectHandle oh,
- std::set<QPDFObjGen>& visited, bool top)
+ std::set<QPDFObjGen>& visited, bool top,
+ int depth)
{
// Traverse the object tree from this point taking care to avoid
// crossing page boundaries.
@@ -397,7 +398,8 @@ QPDF::updateObjectMapsInternal(ObjUser const& ou, QPDFObjectHandle oh,
int n = oh.getArrayNItems();
for (int i = 0; i < n; ++i)
{
- updateObjectMapsInternal(ou, oh.getArrayItem(i), visited, false);
+ updateObjectMapsInternal(
+ ou, oh.getArrayItem(i), visited, false, 1 + depth);
}
}
else if (oh.isDictionary() || oh.isStream())
@@ -417,8 +419,9 @@ QPDF::updateObjectMapsInternal(ObjUser const& ou, QPDFObjectHandle oh,
{
// Traverse page thumbnail dictionaries as a special
// case.
- updateObjectMaps(ObjUser(ObjUser::ou_thumb, ou.pageno),
- dict.getKey(key));
+ updateObjectMapsInternal(
+ ObjUser(ObjUser::ou_thumb, ou.pageno),
+ dict.getKey(key), visited, false, 1 + depth);
}
else if (is_page_node && (key == "/Parent"))
{
@@ -426,8 +429,8 @@ QPDF::updateObjectMapsInternal(ObjUser const& ou, QPDFObjectHandle oh,
}
else
{
- updateObjectMapsInternal(ou, dict.getKey(key),
- visited, false);
+ updateObjectMapsInternal(
+ ou, dict.getKey(key), visited, false, 1 + depth);
}
}
}