From d5cfa906ecbcd005bd1e32f6a78750c998a26ad9 Mon Sep 17 00:00:00 2001 From: Justin Collins Date: Mon, 12 Apr 2021 21:40:38 -0700 Subject: [PATCH] Set line numbers when joining array into a string Fixes #1579 --- lib/brakeman/processors/alias_processor.rb | 10 +++++----- test/tests/alias_processor.rb | 12 ++++++++++++ 2 files changed, 17 insertions(+), 5 deletions(-) diff --git a/lib/brakeman/processors/alias_processor.rb b/lib/brakeman/processors/alias_processor.rb index 46e3064c87..61162e6a14 100644 --- a/lib/brakeman/processors/alias_processor.rb +++ b/lib/brakeman/processors/alias_processor.rb @@ -294,7 +294,7 @@ def process_call exp # Painful conversion of Array#join into string interpolation def process_array_join array, join_str - result = s() + result = s().line(array.line) join_value = if string? join_str join_str.value @@ -332,11 +332,11 @@ def process_array_join array, join_str result.unshift combined_first # Have to fix up strings that follow interpolation - result.reduce(s(:dstr)) do |memo, e| + result.reduce(s(:dstr).line(array.line)) do |memo, e| if string? e and node_type? memo.last, :evstr e.value = "#{join_value}#{e.value}" elsif join_value and node_type? memo.last, :evstr and node_type? e, :evstr - memo << s(:str, join_value) + memo << s(:str, join_value).line(e.line) end memo << e @@ -347,9 +347,9 @@ def join_item item, join_value if item.is_a? String "#{item}#{join_value}" elsif string? item or symbol? item or number? item - s(:str, "#{item.value}#{join_value}") + s(:str, "#{item.value}#{join_value}").line(item.line) else - s(:evstr, item) + s(:evstr, item).line(item.line) end end diff --git a/test/tests/alias_processor.rb b/test/tests/alias_processor.rb index ef01b799ee..6031d44796 100644 --- a/test/tests/alias_processor.rb +++ b/test/tests/alias_processor.rb @@ -1151,6 +1151,18 @@ def test_array_join_lots_of_interp INPUT end + def test_array_join_line_numbers + # Test that line numbers are set for all parts of a joined string + original_sexp = RubyParser.new.parse "z = [x, 1].join(' ')" + processed_sexp = Brakeman::AliasProcessor.new.process_safely(original_sexp) + + assert_equal s(:lasgn, :z, s(:dstr, "", s(:evstr, s(:call, nil, :x)), s(:str, " 1"))), processed_sexp + assert_equal 1, processed_sexp[2].line + assert_equal 1, processed_sexp[2][2].line + assert_equal 1, processed_sexp[2][2][1].line + assert_equal 1, processed_sexp[2][3].line + end + def test_ignore_freeze assert_alias "blah", <<-INPUT x = blah.freeze