brakeman 3.6.2 → 3.7.0

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 (45) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGES +9 -0
  3. data/bundle/load.rb +1 -1
  4. data/bundle/ruby/2.3.0/gems/ruby_parser-3.9.0/lib/rp_extensions.rb +5 -1
  5. data/bundle/ruby/2.3.0/gems/ruby_parser-3.9.0/lib/ruby18_parser.rb +1617 -1613
  6. data/bundle/ruby/2.3.0/gems/ruby_parser-3.9.0/lib/ruby18_parser.y +15 -9
  7. data/bundle/ruby/2.3.0/gems/ruby_parser-3.9.0/lib/ruby19_parser.rb +1572 -1570
  8. data/bundle/ruby/2.3.0/gems/ruby_parser-3.9.0/lib/ruby19_parser.y +19 -15
  9. data/bundle/ruby/2.3.0/gems/ruby_parser-3.9.0/lib/ruby20_parser.rb +2415 -2413
  10. data/bundle/ruby/2.3.0/gems/ruby_parser-3.9.0/lib/ruby20_parser.y +34 -23
  11. data/bundle/ruby/2.3.0/gems/ruby_parser-3.9.0/lib/ruby21_parser.rb +2535 -2515
  12. data/bundle/ruby/2.3.0/gems/ruby_parser-3.9.0/lib/ruby21_parser.y +34 -23
  13. data/bundle/ruby/2.3.0/gems/ruby_parser-3.9.0/lib/ruby22_parser.rb +2558 -2543
  14. data/bundle/ruby/2.3.0/gems/ruby_parser-3.9.0/lib/ruby22_parser.y +35 -24
  15. data/bundle/ruby/2.3.0/gems/ruby_parser-3.9.0/lib/ruby23_parser.rb +2504 -2483
  16. data/bundle/ruby/2.3.0/gems/ruby_parser-3.9.0/lib/ruby23_parser.y +35 -24
  17. data/bundle/ruby/2.3.0/gems/ruby_parser-3.9.0/lib/ruby24_parser.rb +2504 -2483
  18. data/bundle/ruby/2.3.0/gems/ruby_parser-3.9.0/lib/ruby24_parser.y +35 -24
  19. data/bundle/ruby/2.3.0/gems/ruby_parser-3.9.0/lib/ruby_lexer.rb +84 -11
  20. data/bundle/ruby/2.3.0/gems/ruby_parser-3.9.0/lib/ruby_parser.yy +35 -24
  21. data/bundle/ruby/2.3.0/gems/ruby_parser-3.9.0/lib/ruby_parser_extras.rb +112 -89
  22. data/bundle/ruby/2.3.0/gems/ruby_parser-3.9.0/test/test_ruby_lexer.rb +67 -0
  23. data/bundle/ruby/2.3.0/gems/ruby_parser-3.9.0/test/test_ruby_parser.rb +32 -1
  24. data/bundle/ruby/2.3.0/gems/{unicode-display_width-1.2.1 → unicode-display_width-1.3.0}/CHANGELOG.md +4 -0
  25. data/bundle/ruby/2.3.0/gems/{unicode-display_width-1.2.1 → unicode-display_width-1.3.0}/MIT-LICENSE.txt +0 -0
  26. data/bundle/ruby/2.3.0/gems/{unicode-display_width-1.2.1 → unicode-display_width-1.3.0}/README.md +1 -1
  27. data/bundle/ruby/2.3.0/gems/{unicode-display_width-1.2.1 → unicode-display_width-1.3.0}/Rakefile +0 -0
  28. data/bundle/ruby/2.3.0/gems/unicode-display_width-1.3.0/data/display_width.marshal.gz +0 -0
  29. data/bundle/ruby/2.3.0/gems/{unicode-display_width-1.2.1 → unicode-display_width-1.3.0}/lib/unicode/display_width.rb +0 -0
  30. data/bundle/ruby/2.3.0/gems/{unicode-display_width-1.2.1 → unicode-display_width-1.3.0}/lib/unicode/display_width/constants.rb +2 -2
  31. data/bundle/ruby/2.3.0/gems/{unicode-display_width-1.2.1 → unicode-display_width-1.3.0}/lib/unicode/display_width/index.rb +0 -0
  32. data/bundle/ruby/2.3.0/gems/{unicode-display_width-1.2.1 → unicode-display_width-1.3.0}/lib/unicode/display_width/no_string_ext.rb +0 -0
  33. data/bundle/ruby/2.3.0/gems/{unicode-display_width-1.2.1 → unicode-display_width-1.3.0}/lib/unicode/display_width/string_ext.rb +0 -0
  34. data/bundle/ruby/2.3.0/gems/{unicode-display_width-1.2.1 → unicode-display_width-1.3.0}/spec/display_width_spec.rb +0 -0
  35. data/bundle/ruby/2.3.0/gems/{unicode-display_width-1.2.1 → unicode-display_width-1.3.0}/unicode-display_width.gemspec +0 -0
  36. data/lib/brakeman.rb +7 -0
  37. data/lib/brakeman/checks/check_redirect.rb +26 -3
  38. data/lib/brakeman/processors/alias_processor.rb +91 -3
  39. data/lib/brakeman/processors/base_processor.rb +9 -1
  40. data/lib/brakeman/report/ignore/interactive.rb +9 -4
  41. data/lib/brakeman/tracker/constants.rb +11 -2
  42. data/lib/brakeman/version.rb +1 -1
  43. data/lib/ruby_parser/bm_sexp.rb +0 -8
  44. metadata +14 -14
  45. data/bundle/ruby/2.3.0/gems/unicode-display_width-1.2.1/data/display_width.marshal.gz +0 -0
@@ -1153,6 +1153,47 @@ class TestRubyLexer < Minitest::Test
1153
1153
  :tNL, nil, :expr_beg)
1154
1154
  end
1155
1155
 
1156
+ def test_yylex_heredoc_double_squiggly
1157
+ setup_lexer_class Ruby23Parser
1158
+
1159
+ assert_lex3("a = <<~\"EOF\"\n blah blah\n EOF\n\n",
1160
+ nil,
1161
+ :tIDENTIFIER, "a", :expr_cmdarg,
1162
+ :tEQL, "=", :expr_beg,
1163
+ :tSTRING_BEG, "\"", :expr_beg,
1164
+ :tSTRING_CONTENT, "blah blah\n", :expr_beg,
1165
+ :tSTRING_END, "EOF", :expr_end,
1166
+ :tNL, nil, :expr_beg)
1167
+ end
1168
+
1169
+ # mri handles tabs in a pretty specific way:
1170
+ # https://github.com/ruby/ruby/blob/trunk/parse.y#L5925
1171
+ def test_yylex_heredoc_double_squiggly_with_tab_indentation_remaining
1172
+ setup_lexer_class Ruby23Parser
1173
+
1174
+ assert_lex3("a = <<~\"EOF\"\n blah blah\n \tblah blah\n EOF\n\n",
1175
+ nil,
1176
+ :tIDENTIFIER, "a", :expr_cmdarg,
1177
+ :tEQL, "=", :expr_beg,
1178
+ :tSTRING_BEG, "\"", :expr_beg,
1179
+ :tSTRING_CONTENT, "blah blah\n\tblah blah\n", :expr_beg,
1180
+ :tSTRING_END, "EOF", :expr_end,
1181
+ :tNL, nil, :expr_beg)
1182
+ end
1183
+
1184
+ def test_yylex_heredoc_double_squiggly_with_tab_indentation_removed
1185
+ setup_lexer_class Ruby23Parser
1186
+
1187
+ assert_lex3("a = <<~\"EOF\"\n blah blah\n\t blah blah\n EOF\n\n",
1188
+ nil,
1189
+ :tIDENTIFIER, "a", :expr_cmdarg,
1190
+ :tEQL, "=", :expr_beg,
1191
+ :tSTRING_BEG, "\"", :expr_beg,
1192
+ :tSTRING_CONTENT, "blah blah\n blah blah\n", :expr_beg,
1193
+ :tSTRING_END, "EOF", :expr_end,
1194
+ :tNL, nil, :expr_beg)
1195
+ end
1196
+
1156
1197
  def test_yylex_heredoc_double_eos
1157
1198
  refute_lex("a = <<\"EOF\"\nblah",
1158
1199
  :tIDENTIFIER, "a",
@@ -1223,6 +1264,19 @@ class TestRubyLexer < Minitest::Test
1223
1264
  :tNL, nil, :expr_beg)
1224
1265
  end
1225
1266
 
1267
+ def test_yylex_heredoc_none_squiggly
1268
+ setup_lexer_class Ruby23Parser
1269
+
1270
+ assert_lex3("a = <<~EOF\n blah\n blah\n EOF\n",
1271
+ nil,
1272
+ :tIDENTIFIER, "a", :expr_cmdarg,
1273
+ :tEQL, "=", :expr_beg,
1274
+ :tSTRING_BEG, "\"", :expr_beg,
1275
+ :tSTRING_CONTENT, "blah\nblah\n", :expr_beg,
1276
+ :tSTRING_END, "EOF", :expr_end,
1277
+ :tNL, nil, :expr_beg)
1278
+ end
1279
+
1226
1280
  def test_yylex_heredoc_single
1227
1281
  assert_lex3("a = <<'EOF'\n blah blah\nEOF\n\n",
1228
1282
  nil,
@@ -1273,6 +1327,19 @@ class TestRubyLexer < Minitest::Test
1273
1327
  :tNL, nil, :expr_beg)
1274
1328
  end
1275
1329
 
1330
+ def test_yylex_heredoc_single_squiggly
1331
+ setup_lexer_class Ruby23Parser
1332
+
1333
+ assert_lex3("a = <<~'EOF'\n blah blah\n EOF\n\n",
1334
+ nil,
1335
+ :tIDENTIFIER, "a", :expr_cmdarg,
1336
+ :tEQL, "=", :expr_beg,
1337
+ :tSTRING_BEG, "\"", :expr_beg,
1338
+ :tSTRING_CONTENT, "blah blah\n", :expr_beg,
1339
+ :tSTRING_END, "EOF", :expr_end,
1340
+ :tNL, nil, :expr_beg)
1341
+ end
1342
+
1276
1343
  def test_yylex_identifier
1277
1344
  assert_lex3("identifier",
1278
1345
  nil,
@@ -571,6 +571,14 @@ module TestRubyParserShared
571
571
  assert_parse rb, pt
572
572
  end
573
573
 
574
+ def test_str_newline_hash_line_number
575
+ rb = "\"\\n\\n\\n\\n#\"\n1"
576
+ pt = s(:block, s(:str, "\n\n\n\n#").line(1),
577
+ s(:lit, 1).line(2))
578
+
579
+ assert_parse rb, pt
580
+ end
581
+
574
582
  def after_process_hook klass, node, data, input_name, output_name
575
583
  assert_equal 1, @result.line, "should have proper line number"
576
584
  end
@@ -811,7 +819,6 @@ module TestRubyParserShared
811
819
  end
812
820
 
813
821
  def test_parse_line_rescue
814
- skip "not yet"
815
822
  rb = "begin\n a\n rescue\n b\n rescue\n c\n end\n"
816
823
  pt = s(:rescue,
817
824
  s(:call, nil, :a).line(2),
@@ -1709,6 +1716,16 @@ module TestRubyParserShared
1709
1716
  assert_parse rb, pt
1710
1717
  end
1711
1718
 
1719
+ def test_defs_as_arg_with_do_block_inside
1720
+ rb = "p def self.b; x.y do; end; end"
1721
+ pt = s(:call,
1722
+ nil,
1723
+ :p,
1724
+ s(:defs, s(:self), :b, s(:args),
1725
+ s(:iter, s(:call, s(:call, nil, :x), :y), 0)))
1726
+
1727
+ assert_parse rb, pt
1728
+ end
1712
1729
  end
1713
1730
 
1714
1731
  module TestRubyParserShared19Plus
@@ -3239,6 +3256,20 @@ module TestRubyParserShared20Plus
3239
3256
 
3240
3257
  assert_parse rb, pt
3241
3258
  end
3259
+
3260
+ def test_bug_249
3261
+ rb = "mount (Class.new do\ndef initialize\nend\n end).new, :at => 'endpoint'"
3262
+ pt = s(:call, nil, :mount,
3263
+ s(:call,
3264
+ s(:iter,
3265
+ s(:call, s(:const, :Class), :new),
3266
+ 0,
3267
+ s(:defn, :initialize, s(:args), s(:nil))),
3268
+ :new),
3269
+ s(:hash, s(:lit, :at), s(:str, "endpoint")))
3270
+
3271
+ assert_parse rb, pt
3272
+ end
3242
3273
  end
3243
3274
 
3244
3275
  module TestRubyParserShared22Plus
@@ -1,5 +1,9 @@
1
1
  # CHANGELOG
2
2
 
3
+ ## 1.3.0
4
+
5
+ - Unicode 10
6
+
3
7
  ## 1.2.1
4
8
 
5
9
  - Fix bug that `emoji: true` would fail for emoji without modifier
@@ -2,7 +2,7 @@
2
2
 
3
3
  Determines the monospace display width of a string in Ruby. Implementation based on [EastAsianWidth.txt](http://www.unicode.org/Public/UNIDATA/EastAsianWidth.txt) and other data, 100% in Ruby. Other than [wcwidth()](https://github.com/janlelis/wcswidth-ruby), which fulfills a similar purpose, it does not rely on the OS vendor to provide an up-to-date method for measuring string width.
4
4
 
5
- Unicode version: **9.0.0**
5
+ Unicode version: **10.0.0**
6
6
 
7
7
  ## Introduction to Character Widths
8
8
 
@@ -1,7 +1,7 @@
1
1
  module Unicode
2
2
  module DisplayWidth
3
- VERSION = '1.2.1'
4
- UNICODE_VERSION = "9.0.0".freeze
3
+ VERSION = '1.3.0'
4
+ UNICODE_VERSION = "10.0.0".freeze
5
5
  DATA_DIRECTORY = File.expand_path(File.dirname(__FILE__) + '/../../../data/').freeze
6
6
  INDEX_FILENAME = (DATA_DIRECTORY + '/display_width.marshal.gz').freeze
7
7
  end
@@ -90,6 +90,13 @@ module Brakeman
90
90
  options[:quiet] = true
91
91
  end
92
92
 
93
+ if options[:rails4]
94
+ options[:rails3] = true
95
+ elsif options[:rails5]
96
+ options[:rails3] = true
97
+ options[:rails4] = true
98
+ end
99
+
93
100
  options[:output_formats] = get_output_formats options
94
101
  options[:github_url] = get_github_url options
95
102
 
@@ -105,11 +105,34 @@ class Brakeman::CheckRedirect < Brakeman::BaseCheck
105
105
  arg = call.first_arg
106
106
 
107
107
  if hash? arg
108
- if value = hash_access(arg, :only_path)
109
- return true if true?(value)
110
- end
108
+ return has_only_path? arg
111
109
  elsif call? arg and arg.method == :url_for
112
110
  return check_url_for(arg)
111
+ elsif call? arg and hash? arg.first_arg and use_unsafe_hash_method? arg
112
+ return has_only_path? arg.first_arg
113
+ end
114
+
115
+ false
116
+ end
117
+
118
+ def use_unsafe_hash_method? arg
119
+ return call_has_param(arg, :to_unsafe_hash) || call_has_param(arg, :to_unsafe_h)
120
+ end
121
+
122
+ def call_has_param arg, key
123
+ if call? arg and call? arg.target
124
+ target = arg.target
125
+ method = target.method
126
+
127
+ node_type? target.target, :params and method == key
128
+ else
129
+ false
130
+ end
131
+ end
132
+
133
+ def has_only_path? arg
134
+ if value = hash_access(arg, :only_path)
135
+ return true if true?(value)
113
136
  end
114
137
 
115
138
  false
@@ -87,6 +87,73 @@ class Brakeman::AliasProcessor < Brakeman::SexpProcessor
87
87
  end
88
88
  end
89
89
 
90
+ def process_bracket_call exp
91
+ r = replace(exp)
92
+
93
+ if r != exp
94
+ return r
95
+ end
96
+
97
+ exp.arglist = process_default(exp.arglist)
98
+
99
+ r = replace(exp)
100
+
101
+ if r != exp
102
+ return r
103
+ end
104
+
105
+ t = process(exp.target.deep_clone)
106
+
107
+ # sometimes t[blah] has a match in the env
108
+ # but we don't want to actually set the target
109
+ # in case the target is big...which is what this
110
+ # whole method is trying to avoid
111
+ if t != exp.target
112
+ e = exp.deep_clone
113
+ e.target = t
114
+
115
+ r = replace(e)
116
+
117
+ if r != e
118
+ return r
119
+ end
120
+ else
121
+ t = nil
122
+ end
123
+
124
+ if hash? t
125
+ if v = hash_access(t, exp.first_arg)
126
+ v.deep_clone(exp.line)
127
+ else
128
+ case t.node_type
129
+ when :params
130
+ exp.target = PARAMS_SEXP.deep_clone(exp.target.line)
131
+ when :session
132
+ exp.target = SESSION_SEXP.deep_clone(exp.target.line)
133
+ when :cookies
134
+ exp.target = COOKIES_SEXP.deep_clone(exp.target.line)
135
+ end
136
+
137
+ exp
138
+ end
139
+ elsif array? t
140
+ if v = process_array_access(t, exp.args)
141
+ v.deep_clone(exp.line)
142
+ else
143
+ exp
144
+ end
145
+ elsif t
146
+ exp.target = t
147
+ exp
148
+ else
149
+ if exp.target # `self` target is reported as `nil` https://github.com/seattlerb/ruby_parser/issues/250
150
+ exp.target = process_default exp.target
151
+ end
152
+
153
+ exp
154
+ end
155
+ end
156
+
90
157
  ARRAY_CONST = s(:const, :Array)
91
158
  HASH_CONST = s(:const, :Hash)
92
159
  RAILS_TEST = s(:call, s(:call, s(:const, :Rails), :env), :test?)
@@ -99,7 +166,12 @@ class Brakeman::AliasProcessor < Brakeman::SexpProcessor
99
166
  if exp.node_type == :safe_call
100
167
  exp.node_type = :call
101
168
  end
102
- exp = process_default exp
169
+
170
+ if exp.method == :[]
171
+ return process_bracket_call exp
172
+ else
173
+ exp = process_default exp
174
+ end
103
175
 
104
176
  #In case it is replaced with something else
105
177
  unless call? exp
@@ -391,7 +463,7 @@ class Brakeman::AliasProcessor < Brakeman::SexpProcessor
391
463
  # x[:y] = 1
392
464
  def process_attrasgn exp
393
465
  tar_variable = exp.target
394
- target = exp.target = process(exp.target)
466
+ target = process(exp.target)
395
467
  method = exp.method
396
468
  index_arg = exp.first_arg
397
469
  value_arg = exp.second_arg
@@ -406,6 +478,10 @@ class Brakeman::AliasProcessor < Brakeman::SexpProcessor
406
478
  if hash? target
407
479
  env[tar_variable] = hash_insert target.deep_clone, index, value
408
480
  end
481
+
482
+ unless node_type? target, :hash
483
+ exp.target = target
484
+ end
409
485
  elsif method.to_s[-1,1] == "="
410
486
  exp.first_arg = process(index_arg)
411
487
  value = get_rhs(exp)
@@ -413,6 +489,7 @@ class Brakeman::AliasProcessor < Brakeman::SexpProcessor
413
489
  match = Sexp.new(:call, target, method.to_s[0..-2].to_sym)
414
490
 
415
491
  set_value match, value
492
+ exp.target = target
416
493
  else
417
494
  raise "Unrecognized assignment: #{exp}"
418
495
  end
@@ -522,7 +599,14 @@ class Brakeman::AliasProcessor < Brakeman::SexpProcessor
522
599
  exp.rhs = process exp.rhs
523
600
  end
524
601
 
525
- @tracker.add_constant exp.lhs, exp.rhs, :file => current_file_name if @tracker
602
+ if @tracker
603
+ @tracker.add_constant exp.lhs,
604
+ exp.rhs,
605
+ :file => current_file_name,
606
+ :module => @current_module,
607
+ :class => @current_class,
608
+ :method => @current_method
609
+ end
526
610
 
527
611
  if exp.lhs.is_a? Symbol
528
612
  match = Sexp.new(:const, exp.lhs)
@@ -598,6 +682,10 @@ class Brakeman::AliasProcessor < Brakeman::SexpProcessor
598
682
  env.current[var] = condition.target[1]
599
683
  exp[branch_index] = process_if_branch branch
600
684
  env.current[var] = previous_value
685
+ elsif i == 1 and array_include_all_literals? condition and node_type? branch, :return
686
+ var = condition.first_arg
687
+ env.current[var] = condition.target[1]
688
+ exp[branch_index] = process_if_branch branch
601
689
  else
602
690
  exp[branch_index] = process_if_branch branch
603
691
  end
@@ -183,7 +183,15 @@ class Brakeman::BaseProcessor < Brakeman::SexpProcessor
183
183
  end
184
184
 
185
185
  def process_cdecl exp
186
- @tracker.add_constant exp.lhs, exp.rhs, :file => current_file_name if @tracker
186
+ if @tracker
187
+ @tracker.add_constant exp.lhs,
188
+ exp.rhs,
189
+ :file => current_file_name,
190
+ :module => @current_module,
191
+ :class => @current_class,
192
+ :method => @current_method
193
+ end
194
+
187
195
  exp
188
196
  end
189
197
 
@@ -101,7 +101,7 @@ module Brakeman
101
101
  end
102
102
 
103
103
  def pre_show_help
104
- say "-" * 20
104
+ say "-" * 30
105
105
  say "Actions:", :cyan
106
106
  show_help
107
107
  end
@@ -189,7 +189,11 @@ q - Quit, do not update ignored warnings
189
189
  end
190
190
 
191
191
  def process_warnings
192
- @new_warnings.each do |w|
192
+ @warning_count = @new_warnings.length
193
+
194
+ @new_warnings.each_with_index do |w, index|
195
+ @current_index = index
196
+
193
197
  if skip_ignored? w or @skip_rest
194
198
  next
195
199
  elsif @ignore_rest
@@ -261,7 +265,8 @@ q - Quit, do not update ignored warnings
261
265
  end
262
266
 
263
267
  def pretty_display warning
264
- say "-" * 20
268
+ progress = "#{@current_index + 1}/#{@warning_count}"
269
+ say "-------- #{progress} #{"-" * (20 - progress.length)}", :cyan
265
270
  show_confidence warning
266
271
 
267
272
  label "Category"
@@ -302,7 +307,7 @@ q - Quit, do not update ignored warnings
302
307
  end
303
308
 
304
309
  def summarize_changes
305
- say "-" * 20
310
+ say "-" * 30
306
311
 
307
312
  say "Ignoring #{@ignore_config.ignored_warnings.length} warnings", :yellow
308
313
  say "Showing #{@ignore_config.shown_warnings.length} warnings", :green