Commit 32d14f3124108344043cdd00c4505a3613763e66
Committed by
GitHub
Merge pull request #1569 from m-holger/fuzz
Refactor `QPDFAcroFormDocumentHelper::traverseField`: add validation …
Showing
5 changed files
with
16 additions
and
4 deletions
fuzz/CMakeLists.txt
| @@ -165,6 +165,7 @@ set(CORPUS_OTHER | @@ -165,6 +165,7 @@ set(CORPUS_OTHER | ||
| 165 | 5109284021272576.fuzz | 165 | 5109284021272576.fuzz |
| 166 | 5828408539152384.fuzz | 166 | 5828408539152384.fuzz |
| 167 | 6310410941956096.fuzz | 167 | 6310410941956096.fuzz |
| 168 | + 6322553212960768.fuzz | ||
| 168 | 6489005569146880.fuzz | 169 | 6489005569146880.fuzz |
| 169 | ) | 170 | ) |
| 170 | 171 |
fuzz/qpdf_extra/6322553212960768.fuzz
0 → 100644
No preview for this file type
fuzz/qtest/fuzz.test
| @@ -11,7 +11,7 @@ my $td = new TestDriver('fuzz'); | @@ -11,7 +11,7 @@ my $td = new TestDriver('fuzz'); | ||
| 11 | 11 | ||
| 12 | my $qpdf_corpus = $ENV{'QPDF_FUZZ_CORPUS'} || die "must set QPDF_FUZZ_CORPUS"; | 12 | my $qpdf_corpus = $ENV{'QPDF_FUZZ_CORPUS'} || die "must set QPDF_FUZZ_CORPUS"; |
| 13 | 13 | ||
| 14 | -my $n_qpdf_files = 103; # increment when adding new files | 14 | +my $n_qpdf_files = 104; # increment when adding new files |
| 15 | 15 | ||
| 16 | my @fuzzers = ( | 16 | my @fuzzers = ( |
| 17 | ['ascii85' => 1], | 17 | ['ascii85' => 1], |
include/qpdf/QPDFAcroFormDocumentHelper.hh
| @@ -226,7 +226,7 @@ class QPDFAcroFormDocumentHelper: public QPDFDocumentHelper | @@ -226,7 +226,7 @@ class QPDFAcroFormDocumentHelper: public QPDFDocumentHelper | ||
| 226 | 226 | ||
| 227 | private: | 227 | private: |
| 228 | void analyze(); | 228 | void analyze(); |
| 229 | - void traverseField(QPDFObjectHandle const& field, QPDFObjectHandle const& parent, int depth); | 229 | + void traverseField(QPDFObjectHandle field, QPDFObjectHandle const& parent, int depth); |
| 230 | QPDFObjectHandle getOrCreateAcroForm(); | 230 | QPDFObjectHandle getOrCreateAcroForm(); |
| 231 | void adjustInheritedFields( | 231 | void adjustInheritedFields( |
| 232 | QPDFObjectHandle obj, | 232 | QPDFObjectHandle obj, |
libqpdf/QPDFAcroFormDocumentHelper.cc
| @@ -315,7 +315,7 @@ QPDFAcroFormDocumentHelper::analyze() | @@ -315,7 +315,7 @@ QPDFAcroFormDocumentHelper::analyze() | ||
| 315 | 315 | ||
| 316 | void | 316 | void |
| 317 | QPDFAcroFormDocumentHelper::traverseField( | 317 | QPDFAcroFormDocumentHelper::traverseField( |
| 318 | - QPDFObjectHandle const& field, QPDFObjectHandle const& parent, int depth) | 318 | + QPDFObjectHandle field, QPDFObjectHandle const& parent, int depth) |
| 319 | { | 319 | { |
| 320 | if (depth > 100) { | 320 | if (depth > 100) { |
| 321 | // Arbitrarily cut off recursion at a fixed depth to avoid specially crafted files that | 321 | // Arbitrarily cut off recursion at a fixed depth to avoid specially crafted files that |
| @@ -360,7 +360,18 @@ QPDFAcroFormDocumentHelper::traverseField( | @@ -360,7 +360,18 @@ QPDFAcroFormDocumentHelper::traverseField( | ||
| 360 | m->annotation_to_field[og] = QPDFFormFieldObjectHelper(our_field); | 360 | m->annotation_to_field[og] = QPDFFormFieldObjectHelper(our_field); |
| 361 | } | 361 | } |
| 362 | 362 | ||
| 363 | - if (is_field && (field.hasKey("/T"))) { | 363 | + if (is_field && depth != 0 && field["/Parent"] != parent) { |
| 364 | + for (auto const& kid: Array(field["/Parent"]["/Kids"])) { | ||
| 365 | + if (kid == parent) { | ||
| 366 | + field.warn("loop detected while traversing /AcroForm"); | ||
| 367 | + return; | ||
| 368 | + } | ||
| 369 | + } | ||
| 370 | + field.warn("encountered invalid /Parent entry while traversing /AcroForm; correcting"); | ||
| 371 | + field.replaceKey("/Parent", parent); | ||
| 372 | + } | ||
| 373 | + | ||
| 374 | + if (is_field && field.hasKey("/T")) { | ||
| 364 | QPDFFormFieldObjectHelper foh(field); | 375 | QPDFFormFieldObjectHelper foh(field); |
| 365 | std::string name = foh.getFullyQualifiedName(); | 376 | std::string name = foh.getFullyQualifiedName(); |
| 366 | auto old = m->field_to.find(og); | 377 | auto old = m->field_to.find(og); |