From 3e255d6b99dd6a68cbb4b31d8bca6b879f871861 Mon Sep 17 00:00:00 2001 From: Justin Collins Date: Sat, 8 Oct 2022 23:31:56 -0700 Subject: [PATCH] Handle multiple values in case/when ... Fixes #1730 --- lib/brakeman/processors/alias_processor.rb | 33 ++++++++++++++++++---- test/tests/alias_processor.rb | 32 +++++++++++++++++++++ 2 files changed, 60 insertions(+), 5 deletions(-) diff --git a/lib/brakeman/processors/alias_processor.rb b/lib/brakeman/processors/alias_processor.rb index 188421be29..b7377a2598 100644 --- a/lib/brakeman/processors/alias_processor.rb +++ b/lib/brakeman/processors/alias_processor.rb @@ -970,11 +970,27 @@ def equality_check? exp exp.method == :== end + # Not a list of values + # when :example def simple_when? exp node_type? exp[1], :array and - not node_type? exp[1][1], :splat, :array and - (exp[1].length == 2 or - exp[1].all? { |e| e.is_a? Symbol or node_type? e, :lit, :str }) + exp[1].length == 2 and # only one element in the array + not node_type? exp[1][1], :splat, :array + end + + # A list of literal values + # + # when 1,2,3 + # + # or + # + # when *[:a, :b] + def all_literals_when? exp + if array? exp[1] # pretty sure this is always true + all_literals? exp[1] or # simple list, not actually array + (splat_array? exp[1][1] and + all_literals? exp[1][1][1]) + end end def process_case exp @@ -1002,9 +1018,16 @@ def process_case exp scope do @branch_env = env.current + # Process the when value for matching + process_default e[1] + # set value of case var if possible - if case_value and simple_when? e - @branch_env[case_value] = e[1][1] + if case_value + if simple_when? e + @branch_env[case_value] = e[1][1] + elsif all_literals_when? e + @branch_env[case_value] = safe_literal(e.line + 1) + end end # when blocks aren't blocks, they are lists of expressions diff --git a/test/tests/alias_processor.rb b/test/tests/alias_processor.rb index 47818d60d0..1946e07c8b 100644 --- a/test/tests/alias_processor.rb +++ b/test/tests/alias_processor.rb @@ -1214,6 +1214,38 @@ def test_case_value_params OUTPUT end + def test_case_list + assert_output <<-INPUT, <<-OUTPUT + case y + when :a, :b, :c + something(y) + end + INPUT + case y + when :a, :b, :c + something(:BRAKEMAN_SAFE_LITERAL) + end + OUTPUT + end + + def test_case_splat + assert_output <<-INPUT, <<-OUTPUT + x = [1, 2, 3] + + case y + when *x + something(y) + end + INPUT + x = [1, 2, 3] + + case y + when *[1, 2, 3] + something(:BRAKEMAN_SAFE_LITERAL) + end + OUTPUT + end + def test_less_copying_of_arrays_and_hashes assert_output <<-'INPUT', <<-'OUTPUT' x = {}