diff --git a/fuzz/CMakeLists.txt b/fuzz/CMakeLists.txt index 136a518..ea516f0 100644 --- a/fuzz/CMakeLists.txt +++ b/fuzz/CMakeLists.txt @@ -165,6 +165,7 @@ set(CORPUS_OTHER 5109284021272576.fuzz 5828408539152384.fuzz 6310410941956096.fuzz + 6322553212960768.fuzz 6489005569146880.fuzz ) diff --git a/fuzz/qpdf_extra/6322553212960768.fuzz b/fuzz/qpdf_extra/6322553212960768.fuzz new file mode 100644 index 0000000..ac36d74 --- /dev/null +++ b/fuzz/qpdf_extra/6322553212960768.fuzz diff --git a/fuzz/qtest/fuzz.test b/fuzz/qtest/fuzz.test index dba9984..d0036a4 100644 --- a/fuzz/qtest/fuzz.test +++ b/fuzz/qtest/fuzz.test @@ -11,7 +11,7 @@ my $td = new TestDriver('fuzz'); my $qpdf_corpus = $ENV{'QPDF_FUZZ_CORPUS'} || die "must set QPDF_FUZZ_CORPUS"; -my $n_qpdf_files = 103; # increment when adding new files +my $n_qpdf_files = 104; # increment when adding new files my @fuzzers = ( ['ascii85' => 1], diff --git a/include/qpdf/QPDFAcroFormDocumentHelper.hh b/include/qpdf/QPDFAcroFormDocumentHelper.hh index 8aff780..7abdb1c 100644 --- a/include/qpdf/QPDFAcroFormDocumentHelper.hh +++ b/include/qpdf/QPDFAcroFormDocumentHelper.hh @@ -226,7 +226,7 @@ class QPDFAcroFormDocumentHelper: public QPDFDocumentHelper private: void analyze(); - void traverseField(QPDFObjectHandle const& field, QPDFObjectHandle const& parent, int depth); + void traverseField(QPDFObjectHandle field, QPDFObjectHandle const& parent, int depth); QPDFObjectHandle getOrCreateAcroForm(); void adjustInheritedFields( QPDFObjectHandle obj, diff --git a/libqpdf/QPDFAcroFormDocumentHelper.cc b/libqpdf/QPDFAcroFormDocumentHelper.cc index 182da1a..4a39734 100644 --- a/libqpdf/QPDFAcroFormDocumentHelper.cc +++ b/libqpdf/QPDFAcroFormDocumentHelper.cc @@ -315,7 +315,7 @@ QPDFAcroFormDocumentHelper::analyze() void QPDFAcroFormDocumentHelper::traverseField( - QPDFObjectHandle const& field, QPDFObjectHandle const& parent, int depth) + QPDFObjectHandle field, QPDFObjectHandle const& parent, int depth) { if (depth > 100) { // Arbitrarily cut off recursion at a fixed depth to avoid specially crafted files that @@ -360,7 +360,18 @@ QPDFAcroFormDocumentHelper::traverseField( m->annotation_to_field[og] = QPDFFormFieldObjectHelper(our_field); } - if (is_field && (field.hasKey("/T"))) { + if (is_field && depth != 0 && field["/Parent"] != parent) { + for (auto const& kid: Array(field["/Parent"]["/Kids"])) { + if (kid == parent) { + field.warn("loop detected while traversing /AcroForm"); + return; + } + } + field.warn("encountered invalid /Parent entry while traversing /AcroForm; correcting"); + field.replaceKey("/Parent", parent); + } + + if (is_field && field.hasKey("/T")) { QPDFFormFieldObjectHelper foh(field); std::string name = foh.getFullyQualifiedName(); auto old = m->field_to.find(og);