From dd358a8401250eb5b9fe8e106d4c08d0ecc0687c Mon Sep 17 00:00:00 2001 From: Pete Matsyburka Date: Mon, 10 Aug 2026 11:48:05 +0300 Subject: [PATCH] fix infinite loop --- config/initializers/hexapdf.rb | 33 +++++++++++++++++++++++++++++++ lib/templates/find_acro_fields.rb | 6 ++++-- 2 files changed, 37 insertions(+), 2 deletions(-) diff --git a/config/initializers/hexapdf.rb b/config/initializers/hexapdf.rb index 6897b41c..7562ee72 100644 --- a/config/initializers/hexapdf.rb +++ b/config/initializers/hexapdf.rb @@ -124,6 +124,38 @@ module HexaPDF end end + module CycleSafeEachField + def each_field(terminal_only: true) + return to_enum(__method__, terminal_only:) unless block_given? + + seen = Set.new.compare_by_identity + + process_field_array = lambda do |array| + array.each_with_index do |field, index| + next if field.nil? + + unless field.respond_to?(:type) && field.type == :XXAcroFormField + array[index] = field = HexaPDF::Type::AcroForm::Field.wrap(document, field) + end + + next unless seen.add?(field.value) + + if field.terminal_field? + yield(field) + else + yield(field) unless terminal_only + + process_field_array.call(field[:Kids]) + end + end + end + + process_field_array.call(root_fields) + + self + end + end + module CycleSafeFullFieldName def full_field_name(seen = Set.new.compare_by_identity) return field_name unless seen.add?(value) @@ -139,3 +171,4 @@ end HexaPDF::Type::AcroForm::Field.singleton_class.prepend(HexaPDF::CycleSafeInheritedValue) HexaPDF::Type::AcroForm::Field.prepend(HexaPDF::CycleSafeFullFieldName) +HexaPDF::Type::AcroForm::Form.prepend(HexaPDF::CycleSafeEachField) diff --git a/lib/templates/find_acro_fields.rb b/lib/templates/find_acro_fields.rb index c59e381a..16d52add 100644 --- a/lib/templates/find_acro_fields.rb +++ b/lib/templates/find_acro_fields.rb @@ -264,7 +264,7 @@ module Templates [process_fields_array(pdf, fields_index.values), annots_index] end - def process_fields_array(pdf, array, acc = []) + def process_fields_array(pdf, array, acc = [], seen = Set.new.compare_by_identity) array.each_with_index do |field, index| next if field.nil? @@ -272,10 +272,12 @@ module Templates array[index] = field = HexaPDF::Type::AcroForm::Field.wrap(pdf, field) end + next unless seen.add?(field.value) + if field.terminal_field? acc << field else - process_fields_array(pdf, field[:Kids], acc) + process_fields_array(pdf, field[:Kids], acc, seen) end end