Commit 32d14f3124108344043cdd00c4505a3613763e66

Authored by m-holger
Committed by GitHub
2 parents bf615b8c 5d0210a5

Merge pull request #1569 from m-holger/fuzz

Refactor `QPDFAcroFormDocumentHelper::traverseField`: add validation …
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);