Commit 24196c08cb2457ab3e7a6d0226e6c28ac55bb832
1 parent
6cc9489f
Fix loop detection error (fuzz issue 23172)
Showing
5 changed files
with
17 additions
and
9 deletions
ChangeLog
| 1 | +2020-10-22 Jay Berkenbilt <ejb@ql.org> | ||
| 2 | + | ||
| 3 | + * Fix loop detection problem when traversing page thumbnails | ||
| 4 | + during optimization (fuzz issue 23172). | ||
| 5 | + | ||
| 1 | 2020-10-21 Jay Berkenbilt <ejb@ql.org> | 6 | 2020-10-21 Jay Berkenbilt <ejb@ql.org> |
| 2 | 7 | ||
| 3 | * Bug fix: properly handle copying foreign streams that have | 8 | * Bug fix: properly handle copying foreign streams that have |
TODO
| @@ -65,7 +65,6 @@ Fuzz Errors | @@ -65,7 +65,6 @@ Fuzz Errors | ||
| 65 | * https://bugs.chromium.org/p/oss-fuzz/issues/detail?id=<N> | 65 | * https://bugs.chromium.org/p/oss-fuzz/issues/detail?id=<N> |
| 66 | 66 | ||
| 67 | * New: | 67 | * New: |
| 68 | - * 23172: stack overflow (https://oss-fuzz.com/testcase-detail/5719543787028480) | ||
| 69 | * 23599: integer overflow: https://oss-fuzz.com/testcase?key=6290807920525312 | 68 | * 23599: integer overflow: https://oss-fuzz.com/testcase?key=6290807920525312 |
| 70 | * 23642: leak: https://oss-fuzz.com/testcase-detail/4906569690251264 | 69 | * 23642: leak: https://oss-fuzz.com/testcase-detail/4906569690251264 |
| 71 | 70 |
fuzz/qpdf_extra/23172.fuzz
0 → 100644
No preview for this file type
include/qpdf/QPDF.hh
| @@ -1341,7 +1341,8 @@ class QPDF | @@ -1341,7 +1341,8 @@ class QPDF | ||
| 1341 | std::set<QPDFObjGen>& visited); | 1341 | std::set<QPDFObjGen>& visited); |
| 1342 | void updateObjectMaps(ObjUser const& ou, QPDFObjectHandle oh); | 1342 | void updateObjectMaps(ObjUser const& ou, QPDFObjectHandle oh); |
| 1343 | void updateObjectMapsInternal(ObjUser const& ou, QPDFObjectHandle oh, | 1343 | void updateObjectMapsInternal(ObjUser const& ou, QPDFObjectHandle oh, |
| 1344 | - std::set<QPDFObjGen>& visited, bool top); | 1344 | + std::set<QPDFObjGen>& visited, bool top, |
| 1345 | + int depth); | ||
| 1345 | void filterCompressedObjects(std::map<int, int> const& object_stream_data); | 1346 | void filterCompressedObjects(std::map<int, int> const& object_stream_data); |
| 1346 | 1347 | ||
| 1347 | // Type conversion helper methods | 1348 | // Type conversion helper methods |
libqpdf/QPDF_optimization.cc
| @@ -354,12 +354,13 @@ void | @@ -354,12 +354,13 @@ void | ||
| 354 | QPDF::updateObjectMaps(ObjUser const& ou, QPDFObjectHandle oh) | 354 | QPDF::updateObjectMaps(ObjUser const& ou, QPDFObjectHandle oh) |
| 355 | { | 355 | { |
| 356 | std::set<QPDFObjGen> visited; | 356 | std::set<QPDFObjGen> visited; |
| 357 | - updateObjectMapsInternal(ou, oh, visited, true); | 357 | + updateObjectMapsInternal(ou, oh, visited, true, 0); |
| 358 | } | 358 | } |
| 359 | 359 | ||
| 360 | void | 360 | void |
| 361 | QPDF::updateObjectMapsInternal(ObjUser const& ou, QPDFObjectHandle oh, | 361 | QPDF::updateObjectMapsInternal(ObjUser const& ou, QPDFObjectHandle oh, |
| 362 | - std::set<QPDFObjGen>& visited, bool top) | 362 | + std::set<QPDFObjGen>& visited, bool top, |
| 363 | + int depth) | ||
| 363 | { | 364 | { |
| 364 | // Traverse the object tree from this point taking care to avoid | 365 | // Traverse the object tree from this point taking care to avoid |
| 365 | // crossing page boundaries. | 366 | // crossing page boundaries. |
| @@ -397,7 +398,8 @@ QPDF::updateObjectMapsInternal(ObjUser const& ou, QPDFObjectHandle oh, | @@ -397,7 +398,8 @@ QPDF::updateObjectMapsInternal(ObjUser const& ou, QPDFObjectHandle oh, | ||
| 397 | int n = oh.getArrayNItems(); | 398 | int n = oh.getArrayNItems(); |
| 398 | for (int i = 0; i < n; ++i) | 399 | for (int i = 0; i < n; ++i) |
| 399 | { | 400 | { |
| 400 | - updateObjectMapsInternal(ou, oh.getArrayItem(i), visited, false); | 401 | + updateObjectMapsInternal( |
| 402 | + ou, oh.getArrayItem(i), visited, false, 1 + depth); | ||
| 401 | } | 403 | } |
| 402 | } | 404 | } |
| 403 | else if (oh.isDictionary() || oh.isStream()) | 405 | else if (oh.isDictionary() || oh.isStream()) |
| @@ -417,8 +419,9 @@ QPDF::updateObjectMapsInternal(ObjUser const& ou, QPDFObjectHandle oh, | @@ -417,8 +419,9 @@ QPDF::updateObjectMapsInternal(ObjUser const& ou, QPDFObjectHandle oh, | ||
| 417 | { | 419 | { |
| 418 | // Traverse page thumbnail dictionaries as a special | 420 | // Traverse page thumbnail dictionaries as a special |
| 419 | // case. | 421 | // case. |
| 420 | - updateObjectMaps(ObjUser(ObjUser::ou_thumb, ou.pageno), | ||
| 421 | - dict.getKey(key)); | 422 | + updateObjectMapsInternal( |
| 423 | + ObjUser(ObjUser::ou_thumb, ou.pageno), | ||
| 424 | + dict.getKey(key), visited, false, 1 + depth); | ||
| 422 | } | 425 | } |
| 423 | else if (is_page_node && (key == "/Parent")) | 426 | else if (is_page_node && (key == "/Parent")) |
| 424 | { | 427 | { |
| @@ -426,8 +429,8 @@ QPDF::updateObjectMapsInternal(ObjUser const& ou, QPDFObjectHandle oh, | @@ -426,8 +429,8 @@ QPDF::updateObjectMapsInternal(ObjUser const& ou, QPDFObjectHandle oh, | ||
| 426 | } | 429 | } |
| 427 | else | 430 | else |
| 428 | { | 431 | { |
| 429 | - updateObjectMapsInternal(ou, dict.getKey(key), | ||
| 430 | - visited, false); | 432 | + updateObjectMapsInternal( |
| 433 | + ou, dict.getKey(key), visited, false, 1 + depth); | ||
| 431 | } | 434 | } |
| 432 | } | 435 | } |
| 433 | } | 436 | } |