Commit 5d0210a5142db059a4b7f9f69ddfe6ea06de096f

Authored by m-holger
1 parent bf615b8c

Refactor `QPDFAcroFormDocumentHelper::traverseField`: add validation for `/Paren…

…t` consistency to handle invalid entries, and improve loop detection logic.
fuzz/CMakeLists.txt
... ... @@ -165,6 +165,7 @@ set(CORPUS_OTHER
165 165 5109284021272576.fuzz
166 166 5828408539152384.fuzz
167 167 6310410941956096.fuzz
  168 + 6322553212960768.fuzz
168 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 11  
12 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 16 my @fuzzers = (
17 17 ['ascii85' => 1],
... ...
include/qpdf/QPDFAcroFormDocumentHelper.hh
... ... @@ -226,7 +226,7 @@ class QPDFAcroFormDocumentHelper: public QPDFDocumentHelper
226 226  
227 227 private:
228 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 230 QPDFObjectHandle getOrCreateAcroForm();
231 231 void adjustInheritedFields(
232 232 QPDFObjectHandle obj,
... ...
libqpdf/QPDFAcroFormDocumentHelper.cc
... ... @@ -315,7 +315,7 @@ QPDFAcroFormDocumentHelper::analyze()
315 315  
316 316 void
317 317 QPDFAcroFormDocumentHelper::traverseField(
318   - QPDFObjectHandle const& field, QPDFObjectHandle const& parent, int depth)
  318 + QPDFObjectHandle field, QPDFObjectHandle const& parent, int depth)
319 319 {
320 320 if (depth > 100) {
321 321 // Arbitrarily cut off recursion at a fixed depth to avoid specially crafted files that
... ... @@ -360,7 +360,18 @@ QPDFAcroFormDocumentHelper::traverseField(
360 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 375 QPDFFormFieldObjectHelper foh(field);
365 376 std::string name = foh.getFullyQualifiedName();
366 377 auto old = m->field_to.find(og);
... ...