brakeman 1.8.3 → 1.9.0.pre1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (63) hide show
  1. data/README.md +3 -27
  2. data/lib/brakeman.rb +36 -38
  3. data/lib/brakeman/app_tree.rb +90 -0
  4. data/lib/brakeman/call_index.rb +5 -38
  5. data/lib/brakeman/checks.rb +11 -11
  6. data/lib/brakeman/checks/base_check.rb +53 -29
  7. data/lib/brakeman/checks/check_cross_site_scripting.rb +11 -9
  8. data/lib/brakeman/checks/check_evaluation.rb +1 -1
  9. data/lib/brakeman/checks/check_execute.rb +3 -3
  10. data/lib/brakeman/checks/check_link_to.rb +15 -13
  11. data/lib/brakeman/checks/check_link_to_href.rb +1 -1
  12. data/lib/brakeman/checks/check_mail_to.rb +1 -1
  13. data/lib/brakeman/checks/check_mass_assignment.rb +27 -13
  14. data/lib/brakeman/checks/check_redirect.rb +4 -4
  15. data/lib/brakeman/checks/check_select_tag.rb +1 -1
  16. data/lib/brakeman/checks/check_select_vulnerability.rb +1 -1
  17. data/lib/brakeman/checks/check_send.rb +2 -2
  18. data/lib/brakeman/checks/check_session_settings.rb +12 -5
  19. data/lib/brakeman/checks/check_single_quotes.rb +3 -3
  20. data/lib/brakeman/checks/check_skip_before_filter.rb +4 -3
  21. data/lib/brakeman/checks/check_sql.rb +30 -30
  22. data/lib/brakeman/checks/check_translate_bug.rb +11 -10
  23. data/lib/brakeman/checks/check_validation_regex.rb +36 -11
  24. data/lib/brakeman/checks/check_without_protection.rb +1 -1
  25. data/lib/brakeman/options.rb +6 -2
  26. data/lib/brakeman/processor.rb +6 -5
  27. data/lib/brakeman/processors/alias_processor.rb +153 -38
  28. data/lib/brakeman/processors/base_processor.rb +16 -21
  29. data/lib/brakeman/processors/controller_alias_processor.rb +24 -11
  30. data/lib/brakeman/processors/controller_processor.rb +25 -25
  31. data/lib/brakeman/processors/erb_template_processor.rb +6 -7
  32. data/lib/brakeman/processors/erubis_template_processor.rb +2 -3
  33. data/lib/brakeman/processors/gem_processor.rb +5 -4
  34. data/lib/brakeman/processors/haml_template_processor.rb +4 -6
  35. data/lib/brakeman/processors/lib/find_all_calls.rb +3 -3
  36. data/lib/brakeman/processors/lib/find_call.rb +2 -2
  37. data/lib/brakeman/processors/lib/find_return_value.rb +134 -0
  38. data/lib/brakeman/processors/lib/processor_helper.rb +24 -2
  39. data/lib/brakeman/processors/lib/rails2_config_processor.rb +13 -14
  40. data/lib/brakeman/processors/lib/rails2_route_processor.rb +9 -4
  41. data/lib/brakeman/processors/lib/rails3_config_processor.rb +8 -8
  42. data/lib/brakeman/processors/lib/rails3_route_processor.rb +23 -21
  43. data/lib/brakeman/processors/lib/render_helper.rb +2 -2
  44. data/lib/brakeman/processors/library_processor.rb +2 -2
  45. data/lib/brakeman/processors/model_processor.rb +16 -12
  46. data/lib/brakeman/processors/output_processor.rb +2 -1
  47. data/lib/brakeman/processors/template_alias_processor.rb +12 -8
  48. data/lib/brakeman/report.rb +28 -14
  49. data/lib/brakeman/rescanner.rb +5 -5
  50. data/lib/brakeman/scanner.rb +56 -94
  51. data/lib/brakeman/templates/header.html.erb +7 -2
  52. data/lib/brakeman/tracker.rb +14 -4
  53. data/lib/brakeman/util.rb +38 -17
  54. data/lib/brakeman/version.rb +1 -1
  55. data/lib/brakeman/warning.rb +14 -6
  56. data/lib/ruby_parser/bm_sexp.rb +157 -57
  57. data/lib/ruby_parser/bm_sexp_processor.rb +1 -2
  58. metadata +26 -25
  59. data/lib/ruby_parser/ruby18_parser.rb +0 -5544
  60. data/lib/ruby_parser/ruby19_parser.rb +0 -5756
  61. data/lib/ruby_parser/ruby_lexer.rb +0 -1349
  62. data/lib/ruby_parser/ruby_parser.rb +0 -5
  63. data/lib/ruby_parser/ruby_parser_extras.rb +0 -1057
@@ -1,7 +1,6 @@
1
1
  require 'brakeman/checks/base_check'
2
2
 
3
3
  #Check for vulnerability in translate() helper that allows cross-site scripting
4
- #http://groups.google.com/group/rubyonrails-security/browse_thread/thread/2b61d70fb73c7cc5
5
4
  class Brakeman::CheckTranslateBug < Brakeman::BaseCheck
6
5
  Brakeman::Checks.add self
7
6
 
@@ -12,32 +11,34 @@ class Brakeman::CheckTranslateBug < Brakeman::BaseCheck
12
11
  version_between?('3.0.0', '3.0.10') or
13
12
  version_between?('3.1.0', '3.1.1')
14
13
 
15
- if uses_translate?
16
- confidence = CONFIDENCE[:high]
14
+ confidence = if uses_translate?
15
+ CONFIDENCE[:high]
17
16
  else
18
- confidence = CONFIDENCE[:med]
17
+ CONFIDENCE[:med]
19
18
  end
20
19
 
21
20
  version = tracker.config[:rails_version]
21
+ description = "have a vulnerability in the translate helper with keys ending in _html"
22
22
 
23
- if version =~ /^3\.1/
24
- message = "Versions before 3.1.2 have a vulnerability in the translate helper."
23
+ message = if version =~ /^3\.1/
24
+ "Versions before 3.1.2 #{description}."
25
25
  elsif version =~ /^3\.0/
26
- message = "Versions before 3.0.11 have a vulnerability in translate helper."
26
+ "Versions before 3.0.11 #{description}."
27
27
  else
28
- message = "Rails 2.3.x using the rails_xss plugin have a vulnerability in translate helper."
28
+ "Rails 2.3.x using the rails_xss plugin #{description}}."
29
29
  end
30
30
 
31
31
  warn :warning_type => "Cross Site Scripting",
32
32
  :message => message,
33
33
  :confidence => confidence,
34
- :file => gemfile_or_environment
34
+ :file => gemfile_or_environment,
35
+ :link_path => "http://groups.google.com/group/rubyonrails-security/browse_thread/thread/2b61d70fb73c7cc5"
35
36
  end
36
37
  end
37
38
 
38
39
  def uses_translate?
39
40
  Brakeman.debug "Finding calls to translate() or t()"
40
41
 
41
- not tracker.find_call(:target => nil, :methods => [:t, :translate]).empty?
42
+ tracker.find_call(:target => nil, :methods => [:t, :translate]).any?
42
43
  end
43
44
  end
@@ -13,48 +13,73 @@ class Brakeman::CheckValidationRegex < Brakeman::BaseCheck
13
13
  @description = "Report uses of validates_format_of with improper anchors"
14
14
 
15
15
  WITH = Sexp.new(:lit, :with)
16
+ FORMAT = Sexp.new(:lit, :format)
16
17
 
17
18
  def run_check
18
19
  active_record_models.each do |name, model|
19
20
  @current_model = name
20
21
  format_validations = model[:options][:validates_format_of]
22
+
21
23
  if format_validations
22
24
  format_validations.each do |v|
23
- process_validator v
25
+ process_validates_format_of v
26
+ end
27
+ end
28
+
29
+ validates = model[:options][:validates]
30
+
31
+ if validates
32
+ validates.each do |v|
33
+ process_validates v
24
34
  end
25
35
  end
26
36
  end
27
37
  end
28
38
 
29
39
  #Check validates_format_of
30
- def process_validator validator
40
+ def process_validates_format_of validator
31
41
  if value = hash_access(validator.last, WITH)
32
42
  check_regex value, validator
33
43
  end
34
44
  end
35
45
 
46
+ #Check validates ..., :format => ...
47
+ def process_validates validator
48
+ hash_arg = validator.last
49
+ return unless hash? hash_arg
50
+
51
+ value = hash_access(hash_arg, FORMAT)
52
+
53
+ if hash? value
54
+ value = hash_access(value, WITH)
55
+ end
56
+
57
+ if value
58
+ check_regex value, validator
59
+ end
60
+ end
61
+
36
62
  #Issue warning if the regular expression does not use
37
63
  #+\A+ and +\z+
38
64
  def check_regex value, validator
39
65
  return unless regexp? value
40
66
 
41
67
  regex = value.value.inspect
42
- if regex =~ /^\/(.{2}).*(.{2})\/(m|i|x|n|e|u|s|o)*\z/
43
- if $1 != "\\A" or ($2 != "\\Z" and $2 != "\\z")
44
- warn :model => @current_model,
45
- :warning_type => "Format Validation",
46
- :message => "Insufficient validation for '#{get_name validator}' using #{value.value.inspect}. Use \\A and \\z as anchors",
47
- :line => value.line,
48
- :confidence => CONFIDENCE[:high]
49
- end
68
+ unless regex =~ /\A\/\\A.*\\(z|Z)\/(m|i|x|n|e|u|s|o)*\z/
69
+ warn :model => @current_model,
70
+ :warning_type => "Format Validation",
71
+ :message => "Insufficient validation for '#{get_name validator}' using #{regex}. Use \\A and \\z as anchors",
72
+ :line => value.line,
73
+ :confidence => CONFIDENCE[:high]
50
74
  end
51
75
  end
52
76
 
53
77
  #Get the name of the attribute being validated.
54
78
  def get_name validator
55
79
  name = validator[1]
80
+
56
81
  if sexp? name
57
- name[1]
82
+ name.value
58
83
  else
59
84
  name
60
85
  end
@@ -33,7 +33,7 @@ class Brakeman::CheckWithoutProtection < Brakeman::BaseCheck
33
33
  #All results should be Model.new(...) or Model.attributes=() calls
34
34
  def process_result res
35
35
  call = res[:call]
36
- last_arg = call.args.last
36
+ last_arg = call.last_arg
37
37
 
38
38
  if hash? last_arg and not call.original_line and not duplicate? res
39
39
 
@@ -50,8 +50,8 @@ module Brakeman::Options
50
50
  opts.separator ""
51
51
  opts.separator "Scanning options:"
52
52
 
53
- opts.on "-a", "--assume-routes", "Assume all controller methods are actions" do
54
- options[:assume_all_routes] = true
53
+ opts.on "-a", "--[no-]assume-routes", "Assume all controller methods are actions (default)" do |assume|
54
+ options[:assume_all_routes] = assume
55
55
  end
56
56
 
57
57
  opts.on "-e", "--escape-html", "Escape HTML by default" do
@@ -71,6 +71,10 @@ module Brakeman::Options
71
71
  options[:ignore_attr_protected] = true
72
72
  end
73
73
 
74
+ opts.on "--interprocedural", "Process method calls to known methods" do
75
+ options[:interprocedural] = true
76
+ end
77
+
74
78
  opts.on "--no-branching", "Disable flow sensitivity on conditionals" do
75
79
  options[:ignore_ifs] = true
76
80
  end
@@ -12,8 +12,9 @@ module Brakeman
12
12
  class Processor
13
13
  include Util
14
14
 
15
- def initialize options
16
- @tracker = Tracker.new self, options
15
+ def initialize(app_tree, options)
16
+ @app_tree = app_tree
17
+ @tracker = Tracker.new(@app_tree, self, options)
17
18
  end
18
19
 
19
20
  def tracked_events
@@ -38,7 +39,7 @@ module Brakeman
38
39
  #Process controller source. +file_name+ is used for reporting
39
40
  def process_controller src, file_name
40
41
  if contains_class? src
41
- ControllerProcessor.new(@tracker).process_controller src, file_name
42
+ ControllerProcessor.new(@app_tree, @tracker).process_controller src, file_name
42
43
  else
43
44
  LibraryProcessor.new(@tracker).process_library src, file_name
44
45
  end
@@ -47,13 +48,13 @@ module Brakeman
47
48
  #Process variable aliasing in controller source and save it in the
48
49
  #tracker.
49
50
  def process_controller_alias name, src, only_method = nil
50
- ControllerAliasProcessor.new(@tracker, only_method).process_controller name, src
51
+ ControllerAliasProcessor.new(@app_tree, @tracker, only_method).process_controller name, src
51
52
  end
52
53
 
53
54
  #Process a model source
54
55
  def process_model src, file_name
55
56
  result = ModelProcessor.new(@tracker).process_model src, file_name
56
- AliasProcessor.new(@tracker).process result
57
+ AliasProcessor.new(@tracker).process_all result if result
57
58
  end
58
59
 
59
60
  #Process either an ERB or HAML template
@@ -24,6 +24,8 @@ class Brakeman::AliasProcessor < Brakeman::SexpProcessor
24
24
  @exp_context = []
25
25
  @current_module = nil
26
26
  @tracker = tracker #set in subclass as necessary
27
+ @helper_method_cache = {}
28
+ @helper_method_info = Hash.new({})
27
29
  set_env_defaults
28
30
  end
29
31
 
@@ -70,11 +72,9 @@ class Brakeman::AliasProcessor < Brakeman::SexpProcessor
70
72
  @exp_context.push exp
71
73
 
72
74
  begin
73
- exp.each_with_index do |e, i|
74
- next if i == 0
75
-
75
+ exp.map! do |e|
76
76
  if sexp? e and not e.empty?
77
- exp[i] = process e
77
+ process e
78
78
  else
79
79
  e
80
80
  end
@@ -107,7 +107,6 @@ class Brakeman::AliasProcessor < Brakeman::SexpProcessor
107
107
 
108
108
  target = exp.target
109
109
  method = exp.method
110
- args = exp[3]
111
110
  first_arg = exp.first_arg
112
111
 
113
112
  #See if it is possible to simplify some basic cases
@@ -154,7 +153,7 @@ class Brakeman::AliasProcessor < Brakeman::SexpProcessor
154
153
  temp_exp = process_array_access target, exp.args
155
154
  exp = temp_exp if temp_exp
156
155
  elsif hash? target
157
- temp_exp = process_hash_access target, exp.args
156
+ temp_exp = process_hash_access target, first_arg
158
157
  exp = temp_exp if temp_exp
159
158
  end
160
159
  when :merge!, :update
@@ -204,7 +203,7 @@ class Brakeman::AliasProcessor < Brakeman::SexpProcessor
204
203
  def process_methdef exp
205
204
  env.scope do
206
205
  set_env_defaults
207
- process exp.body
206
+ exp.body = process_all! exp.body
208
207
  end
209
208
  exp
210
209
  end
@@ -213,7 +212,7 @@ class Brakeman::AliasProcessor < Brakeman::SexpProcessor
213
212
  def process_selfdef exp
214
213
  env.scope do
215
214
  set_env_defaults
216
- process exp.body
215
+ exp.body = process_all! exp.body
217
216
  end
218
217
  exp
219
218
  end
@@ -231,8 +230,10 @@ class Brakeman::AliasProcessor < Brakeman::SexpProcessor
231
230
 
232
231
  if @inside_if and val = env[local]
233
232
  #avoid setting to value it already is (e.g. "1 or 1")
234
- if val != exp.rhs and val[1] != exp.rhs and val[2] != exp.rhs
235
- env[local] = Sexp.new(:or, val, exp.rhs).line(exp.line || -2)
233
+ if val != exp.rhs
234
+ unless node_type?(val, :or) and (val.rhs == exp.rhs or val.lhs == exp.rhs)
235
+ env[local] = Sexp.new(:or, val, exp.rhs).line(exp.line || -2)
236
+ end
236
237
  end
237
238
  else
238
239
  env[local] = exp.rhs
@@ -300,21 +301,22 @@ class Brakeman::AliasProcessor < Brakeman::SexpProcessor
300
301
  tar_variable = exp.target
301
302
  target = exp.target = process(exp.target)
302
303
  method = exp.method
303
- args = exp.args
304
+ index_arg = exp.first_arg
305
+ value_arg = exp.second_arg
304
306
 
305
307
  if method == :[]=
306
- index = exp.first_arg = process(args.first)
307
- value = exp.second_arg = process(args.second)
308
- match = Sexp.new(:call, target, :[], Sexp.new(:arglist, index))
308
+ index = exp.first_arg = process(index_arg)
309
+ value = exp.second_arg = process(value_arg)
310
+ match = Sexp.new(:call, target, :[], index)
309
311
  env[match] = value
310
312
 
311
313
  if hash? target
312
314
  env[tar_variable] = hash_insert target.deep_clone, index, value
313
315
  end
314
316
  elsif method.to_s[-1,1] == "="
315
- value = exp.first_arg = process(args.first)
317
+ value = exp.first_arg = process(index_arg)
316
318
  #This is what we'll replace with the value
317
- match = Sexp.new(:call, target, method.to_s[0..-2].to_sym, Sexp.new(:arglist))
319
+ match = Sexp.new(:call, target, method.to_s[0..-2].to_sym)
318
320
 
319
321
  if @inside_if and val = env[match]
320
322
  if val != value
@@ -336,7 +338,7 @@ class Brakeman::AliasProcessor < Brakeman::SexpProcessor
336
338
  hash = hash.deep_clone
337
339
  hash_iterate args do |key, replacement|
338
340
  hash_insert hash, key, replacement
339
- match = Sexp.new(:call, hash, :[], Sexp.new(:arglist, key))
341
+ match = Sexp.new(:call, hash, :[], key)
340
342
  env[match] = replacement
341
343
  end
342
344
  hash
@@ -361,7 +363,7 @@ class Brakeman::AliasProcessor < Brakeman::SexpProcessor
361
363
  target = exp[1] = process(exp[1])
362
364
  index = exp[2][1] = process(exp[2][1])
363
365
  value = exp[4] = process(exp[4])
364
- match = Sexp.new(:call, target, :[], Sexp.new(:arglist, index))
366
+ match = Sexp.new(:call, target, :[], index)
365
367
 
366
368
  unless env[match]
367
369
  if request_value? target
@@ -383,7 +385,7 @@ class Brakeman::AliasProcessor < Brakeman::SexpProcessor
383
385
  value = exp[4] = process(exp[4])
384
386
  method = exp[2]
385
387
 
386
- match = Sexp.new(:call, target, method.to_s[0..-2].to_sym, Sexp.new(:arglist))
388
+ match = Sexp.new(:call, target, method.to_s[0..-2].to_sym)
387
389
 
388
390
  unless env[match]
389
391
  env[match] = value
@@ -392,8 +394,10 @@ class Brakeman::AliasProcessor < Brakeman::SexpProcessor
392
394
  exp
393
395
  end
394
396
 
397
+ #This is the right hand side value of a multiple assignment,
398
+ #like `x = y, z`
395
399
  def process_svalue exp
396
- exp[1]
400
+ exp.value
397
401
  end
398
402
 
399
403
  #Constant assignments like
@@ -423,9 +427,9 @@ class Brakeman::AliasProcessor < Brakeman::SexpProcessor
423
427
  if true? condition
424
428
  exps = [exp.then_clause]
425
429
  elsif false? condition
426
- exps = exp[3..-1]
430
+ exps = [exp.else_clause]
427
431
  else
428
- exps = exp[2..-1]
432
+ exps = [exp.then_clause, exp.else_clause]
429
433
  end
430
434
 
431
435
  was_inside = @inside_if
@@ -461,15 +465,9 @@ class Brakeman::AliasProcessor < Brakeman::SexpProcessor
461
465
  end
462
466
 
463
467
  #Process hash access by returning the value associated
464
- #with the given arguments.
465
- def process_hash_access target, args
466
- if args.length == 1
467
- index = args[0]
468
-
469
- hash_access(target, index)
470
- else
471
- nil
472
- end
468
+ #with the given argument.
469
+ def process_hash_access target, index
470
+ hash_access(target, index)
473
471
  end
474
472
 
475
473
  #Join two array literals into one.
@@ -482,8 +480,9 @@ class Brakeman::AliasProcessor < Brakeman::SexpProcessor
482
480
  #Join two string literals into one.
483
481
  def join_strings string1, string2
484
482
  result = Sexp.new(:str)
485
- result[1] = string1[1] + string2[1]
486
- if result[1].length > 50
483
+ result.value = string1.value + string2.value
484
+
485
+ if result.value.length > 50
487
486
  string1
488
487
  else
489
488
  result
@@ -492,18 +491,19 @@ class Brakeman::AliasProcessor < Brakeman::SexpProcessor
492
491
 
493
492
  #Returns a new SexpProcessor::Environment containing only instance variables.
494
493
  #This is useful, for example, when processing views.
495
- def only_ivars include_request_vars = false
494
+ def only_ivars include_request_vars = false, lenv = nil
495
+ lenv ||= env
496
496
  res = SexpProcessor::Environment.new
497
497
 
498
498
  if include_request_vars
499
- env.all.each do |k, v|
499
+ lenv.all.each do |k, v|
500
500
  #TODO Why would this have nil values?
501
501
  if (k.node_type == :ivar or request_value? k) and not v.nil?
502
502
  res[k] = v.dup
503
503
  end
504
504
  end
505
505
  else
506
- env.all.each do |k, v|
506
+ lenv.all.each do |k, v|
507
507
  #TODO Why would this have nil values?
508
508
  if k.node_type == :ivar and not v.nil?
509
509
  res[k] = v.dup
@@ -514,6 +514,117 @@ class Brakeman::AliasProcessor < Brakeman::SexpProcessor
514
514
  res
515
515
  end
516
516
 
517
+ def only_request_vars
518
+ res = SexpProcessor::Environment.new
519
+
520
+ env.all.each do |k, v|
521
+ if request_value? k and not v.nil?
522
+ res[k] = v.dup
523
+ end
524
+ end
525
+
526
+ res
527
+ end
528
+
529
+ def get_call_value call
530
+ method_name = call.method
531
+
532
+ #Look for helper methods and see if we can get a return value
533
+ if found_method = find_method(method_name, @current_class)
534
+ helper = found_method[:method]
535
+
536
+ if sexp? helper
537
+ value = process_helper_method helper, call.args
538
+ value.line(call.line)
539
+ return value
540
+ else
541
+ raise "Unexpected value for method: #{found_method}"
542
+ end
543
+ else
544
+ call
545
+ end
546
+ end
547
+
548
+ def process_helper_method method_exp, args
549
+ method_name = method_exp.method_name
550
+ Brakeman.debug "Processing method #{method_name}"
551
+
552
+ info = @helper_method_info[method_name]
553
+
554
+ #If method uses instance variables, then include those and request
555
+ #variables (params, etc) in the method environment. Otherwise,
556
+ #only include request variables.
557
+ if info[:uses_ivars]
558
+ meth_env = only_ivars(:include_request_vars)
559
+ else
560
+ meth_env = only_request_vars
561
+ end
562
+
563
+ #Add arguments to method environment
564
+ assign_args method_exp, args, meth_env
565
+
566
+
567
+ #Find return values if method does not depend on environment/args
568
+ values = @helper_method_cache[method_name]
569
+
570
+ unless values
571
+ #Serialize environment for cache key
572
+ meth_values = meth_env.instance_variable_get(:@env).to_a
573
+ meth_values.sort!
574
+ meth_values = meth_values.to_s
575
+
576
+ digest = Digest::SHA1.new.update(meth_values << method_name.to_s).to_s.to_sym
577
+
578
+ values = @helper_method_cache[digest]
579
+ end
580
+
581
+ if values
582
+ #Use values from cache
583
+ values[:ivar_values].each do |var, val|
584
+ env[var] = val
585
+ end
586
+
587
+ values[:return_value]
588
+ else
589
+ #Find return value for method
590
+ frv = Brakeman::FindReturnValue.new
591
+ value = frv.get_return_value(method_exp.body_list, meth_env)
592
+
593
+ ivars = {}
594
+
595
+ only_ivars(false, meth_env).all.each do |var, val|
596
+ env[var] = val
597
+ ivars[var] = val
598
+ end
599
+
600
+ if not frv.uses_ivars? and args.length == 0
601
+ #Store return value without ivars and args if they are not used
602
+ @helper_method_cache[method_exp.method_name] = { :return_value => value, :ivar_values => ivars }
603
+ else
604
+ @helper_method_cache[digest] = { :return_value => value, :ivar_values => ivars }
605
+ end
606
+
607
+ #Store information about method, just ivar usage for now
608
+ @helper_method_info[method_name] = { :uses_ivars => frv.uses_ivars? }
609
+
610
+ value
611
+ end
612
+ end
613
+
614
+ def assign_args method_exp, args, meth_env = SexpProcessor::Environment.new
615
+ formal_args = method_exp.formal_args
616
+
617
+ formal_args.each_with_index do |arg, index|
618
+ next if index == 0
619
+
620
+ if arg.is_a? Symbol and sexp? args[index - 1]
621
+ meth_env[Sexp.new(:lvar, arg)] = args[index - 1]
622
+ end
623
+ end
624
+
625
+ meth_env
626
+ end
627
+
517
628
  #Set line nunber for +exp+ and every Sexp it contains. Used when replacing
518
629
  #expressions, so warnings indicate the correct line.
519
630
  def set_line exp, line_number
@@ -530,8 +641,8 @@ class Brakeman::AliasProcessor < Brakeman::SexpProcessor
530
641
 
531
642
  #Finds the inner most call target which is not the target of a call to <<
532
643
  def find_push_target exp
533
- if call? exp and exp[2] == :<<
534
- find_push_target exp[1]
644
+ if call? exp and exp.method == :<<
645
+ find_push_target exp.target
535
646
  else
536
647
  exp
537
648
  end
@@ -544,4 +655,8 @@ class Brakeman::AliasProcessor < Brakeman::SexpProcessor
544
655
 
545
656
  false
546
657
  end
658
+
659
+ def find_method *args
660
+ nil
661
+ end
547
662
  end