From 2eabc44f1a1874c3707964279db8aa7c3793bf1e Mon Sep 17 00:00:00 2001 From: Keenan Brock Date: Thu, 4 Apr 2019 15:21:20 -0400 Subject: [PATCH] fix_auth now handles recursive settings situation: 1. For one customer, miq_request_tasks has an options hash with recursive values. 2. fix_auth recurses all the options looking for passwords to convert before: it recurses forever after: it now detects the recursion and does not go forever NOTE: this only detects very simple recursive cases. https://bugzilla.redhat.com/show_bug.cgi?id=1696237 --- lib/vmdb/settings_walker.rb | 3 +- spec/lib/vmdb/settings_spec.rb | 77 ++++++++++++++++++++++------------ 2 files changed, 53 insertions(+), 27 deletions(-) diff --git a/lib/vmdb/settings_walker.rb b/lib/vmdb/settings_walker.rb index ecbbfebb33a..47a0cf1baf3 100644 --- a/lib/vmdb/settings_walker.rb +++ b/lib/vmdb/settings_walker.rb @@ -20,13 +20,14 @@ def walk(settings, path = [], &block) key_path = path.dup << key yield key, value, key_path, settings + next if key == settings || value == settings case value when settings.class walk(value, key_path, &block) when Array value.each_with_index do |v, i| - walk(v, key_path.dup << i, &block) if v.kind_of?(settings.class) + walk(v, key_path.dup << i, &block) if v.kind_of?(settings.class) && v != settings end end end diff --git a/spec/lib/vmdb/settings_spec.rb b/spec/lib/vmdb/settings_spec.rb index 7f393c85c7b..80be3bb3d9a 100644 --- a/spec/lib/vmdb/settings_spec.rb +++ b/spec/lib/vmdb/settings_spec.rb @@ -35,36 +35,61 @@ end end - it ".walk" do - stub_settings(:a => {:b => 'c'}, :d => {:e => {:f => 'g'}}, :i => [{:j => 'k'}, {:l => 'm'}]) - - walked = [] - described_class.walk do |key, value, path, owning| - expect(owning).to be_kind_of(Config::Options) - - if %i(a d e).include?(key) - expect(value).to be_kind_of(Config::Options) - value = value.to_hash - elsif %i(i).include?(key) - expect(value).to be_kind_of(Array) - value.each { |v| expect(v).to be_kind_of(Config::Options) } - value = value.collect(&:to_hash) + describe ".walk" do + it "traverses tree properly" do + stub_settings(:a => {:b => 'c'}, :d => {:e => {:f => 'g'}}, :i => [{:j => 'k'}, {:l => 'm'}]) + + walked = [] + described_class.walk do |key, value, path, owning| + expect(owning).to be_kind_of(Config::Options) + + if %i(a d e).include?(key) + expect(value).to be_kind_of(Config::Options) + value = value.to_hash + elsif %i(i).include?(key) + expect(value).to be_kind_of(Array) + value.each { |v| expect(v).to be_kind_of(Config::Options) } + value = value.collect(&:to_hash) + end + + walked << [key, value, path] end - walked << [key, value, path] + expect(walked).to eq [ + #key value path + [:a, {:b => 'c'}, [:a]], + [:b, 'c', [:a, :b]], + [:d, {:e => {:f => 'g'}}, [:d]], + [:e, {:f => 'g'}, [:d, :e]], + [:f, 'g', [:d, :e, :f]], + [:i, [{:j => 'k'}, {:l => 'm'}], [:i]], + [:j, 'k', [:i, 0, :j]], + [:l, 'm', [:i, 1, :l]], + ] + end + + it "handles basic recursion (value == settings)" do + y = YAML.load(<<~CONFIG) + --- + :hash: + - &1 + A: *1 + CONFIG + + expect { described_class.walk(y) { |_k, _v, _p, _o| } }.not_to raise_error + end + + it "handles hash recursion (embedded array == settings)" do + s = {:a => []} + s[:a] << s + expect { described_class.walk(s) { |_k, _v, _p, _o| } }.not_to raise_error end - expect(walked).to eq [ - #key value path - [:a, {:b => 'c'}, [:a]], - [:b, 'c', [:a, :b]], - [:d, {:e => {:f => 'g'}}, [:d]], - [:e, {:f => 'g'}, [:d, :e]], - [:f, 'g', [:d, :e, :f]], - [:i, [{:j => 'k'}, {:l => 'm'}], [:i]], - [:j, 'k', [:i, 0, :j]], - [:l, 'm', [:i, 1, :l]], - ] + it "handles array recursion (key == settings)" do + s = [] + s << s + expect { described_class.walk(s) { |_k, _v, _p, _o| } }.not_to raise_error + end end describe ".save!" do