diff --git a/lib/miq_expression.rb b/lib/miq_expression.rb index 02851f89626..aae86a30f26 100644 --- a/lib/miq_expression.rb +++ b/lib/miq_expression.rb @@ -640,16 +640,7 @@ def self.quote(val, typ) val.to_s.to_f_with_method when "numeric_set" val = val.split(",") if val.kind_of?(String) - v_arr = Array.wrap(val).flat_map do |v| - if v.kind_of?(String) - v = begin - eval(v) - rescue - nil - end - end - v.kind_of?(Range) ? v.to_a : v - end.compact.uniq.sort + v_arr = Array.wrap(val).flat_map { |v| quote_numeric_set_atom(v) }.compact.uniq.sort "[#{v_arr.join(",")}]" when "string_set" val = val.split(",") if val.kind_of?(String) @@ -660,6 +651,32 @@ def self.quote(val, typ) end end + private_class_method def self.quote_numeric_set_atom(val) + val = val.to_s unless val.kind_of?(Numeric) || val.kind_of?(Range) + + if val.kind_of?(String) + val = val.strip + val = + if val.include?("..") # Parse Ranges + b, e = val.split("..", 2).map do |i| + if integer?(i) + i.to_i_with_method + elsif numeric?(i) + i.to_f_with_method + end + end + + Range.new(b, e) if b && e + elsif integer?(val) # Parse Integers + val.to_i_with_method + elsif numeric?(val) # Parse Floats + val.to_f_with_method + end + end + + val.kind_of?(Range) ? val.to_a : val + end + def self.quote_human(val, typ) case typ.to_s when "integer", "decimal", "fixnum", "float" diff --git a/spec/lib/miq_expression_spec.rb b/spec/lib/miq_expression_spec.rb index d30d0e04199..04bec549fc8 100644 --- a/spec/lib/miq_expression_spec.rb +++ b/spec/lib/miq_expression_spec.rb @@ -1366,9 +1366,34 @@ expect { exp.to_ruby }.to raise_error(/operator 'RUBY' is not supported/) end - it "tests numeric set expressions" do - exp = MiqExpression.new("=" => {"field" => "Host-enabled_inbound_ports", "value" => "22,427,5988,5989"}) - expect(exp.to_ruby).to eq('/virtual/enabled_inbound_ports == [22,427,5988,5989]') + it "ignores invalid values for a numeric_set in an = expression" do + actual = described_class.new("=" => {"field" => "Host-enabled_inbound_ports", "value" => "22, 427, 5988, 5989, foo, `echo 1000`.to_i, abc..123, 1..4"}).to_ruby + expected = "/virtual/enabled_inbound_ports == [1,2,3,4,22,427,5988,5989]" + expect(actual).to eq(expected) + end + + it "ignores invalid values for a numeric_set in an INCLUDES ALL expression" do + actual = described_class.new("INCLUDES ALL" => {"field" => "Host-enabled_inbound_ports", "value" => "22, 427, 5988, 5989, foo, `echo 1000`.to_i, abc..123, 1..4"}).to_ruby + expected = "(/virtual/enabled_inbound_ports & [1,2,3,4,22,427,5988,5989]) == [1,2,3,4,22,427,5988,5989]" + expect(actual).to eq(expected) + end + + it "ignores invalid values for a numeric_set in an INCLUDES ANY expression" do + actual = described_class.new("INCLUDES ANY" => {"field" => "Host-enabled_inbound_ports", "value" => "22, 427, 5988, 5989, foo, `echo 1000`.to_i, abc..123, 1..4"}).to_ruby + expected = "([1,2,3,4,22,427,5988,5989] - /virtual/enabled_inbound_ports) != [1,2,3,4,22,427,5988,5989]" + expect(actual).to eq(expected) + end + + it "ignores invalid values for a numeric_set in an INCLUDES ONLY expression" do + actual = described_class.new("INCLUDES ONLY" => {"field" => "Host-enabled_inbound_ports", "value" => "22, 427, 5988, 5989, foo, `echo 1000`.to_i, abc..123, 1..4"}).to_ruby + expected = "(/virtual/enabled_inbound_ports - [1,2,3,4,22,427,5988,5989]) == []" + expect(actual).to eq(expected) + end + + it "ignores invalid values for a numeric_set in an LIMITED TO expression" do + actual = described_class.new("LIMITED TO" => {"field" => "Host-enabled_inbound_ports", "value" => "22, 427, 5988, 5989, foo, `echo 1000`.to_i, abc..123, 1..4"}).to_ruby + expected = "(/virtual/enabled_inbound_ports - [1,2,3,4,22,427,5988,5989]) == []" + expect(actual).to eq(expected) end it "escapes forward slashes for values in REGULAR EXPRESSION MATCHES expressions" do @@ -1476,10 +1501,10 @@ exp: INCLUDES ANY: field: Host-enabled_inbound_ports - value: 22, 427, 5988, 5989, 1..3 + value: 22, 427, 5988, 5989, 1..4 ' - expected = "([1,2,3,22,427,5988,5989] - /virtual/enabled_inbound_ports) != [1,2,3,22,427,5988,5989]" + expected = "([1,2,3,4,22,427,5988,5989] - /virtual/enabled_inbound_ports) != [1,2,3,4,22,427,5988,5989]" expect(filter.to_ruby).to eq(expected) end @@ -1488,10 +1513,10 @@ exp: INCLUDES ONLY: field: Host-enabled_inbound_ports - value: 22 + value: 22, 427, 5988, 5989, 1..4 ' - expected = "(/virtual/enabled_inbound_ports - [22]) == []" + expected = "(/virtual/enabled_inbound_ports - [1,2,3,4,22,427,5988,5989]) == []" expect(filter.to_ruby).to eq(expected) end @@ -1500,10 +1525,10 @@ exp: LIMITED TO: field: Host-enabled_inbound_ports - value: 22 + value: 22, 427, 5988, 5989, 1..4 ' - expected = "(/virtual/enabled_inbound_ports - [22]) == []" + expected = "(/virtual/enabled_inbound_ports - [1,2,3,4,22,427,5988,5989]) == []" expect(filter.to_ruby).to eq(expected) end