brakeman-min 0.5.2 → 2.1.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (152) hide show
  1. data/CHANGES +529 -0
  2. data/README.md +74 -28
  3. data/bin/brakeman +60 -266
  4. data/lib/brakeman.rb +422 -0
  5. data/lib/brakeman/app_tree.rb +101 -0
  6. data/lib/brakeman/brakeman.rake +10 -0
  7. data/lib/brakeman/call_index.rb +215 -0
  8. data/lib/brakeman/checks.rb +180 -0
  9. data/lib/brakeman/checks/base_check.rb +538 -0
  10. data/lib/brakeman/checks/check_basic_auth.rb +89 -0
  11. data/lib/brakeman/checks/check_content_tag.rb +162 -0
  12. data/lib/brakeman/checks/check_cross_site_scripting.rb +334 -0
  13. data/lib/{checks → brakeman/checks}/check_default_routes.rb +13 -6
  14. data/lib/brakeman/checks/check_deserialize.rb +57 -0
  15. data/lib/brakeman/checks/check_digest_dos.rb +38 -0
  16. data/lib/brakeman/checks/check_escape_function.rb +21 -0
  17. data/lib/brakeman/checks/check_evaluation.rb +33 -0
  18. data/lib/brakeman/checks/check_execute.rb +98 -0
  19. data/lib/brakeman/checks/check_file_access.rb +62 -0
  20. data/lib/brakeman/checks/check_filter_skipping.rb +31 -0
  21. data/lib/brakeman/checks/check_forgery_setting.rb +54 -0
  22. data/lib/brakeman/checks/check_jruby_xml.rb +38 -0
  23. data/lib/brakeman/checks/check_json_parsing.rb +102 -0
  24. data/lib/brakeman/checks/check_link_to.rb +132 -0
  25. data/lib/brakeman/checks/check_link_to_href.rb +92 -0
  26. data/lib/{checks → brakeman/checks}/check_mail_to.rb +14 -13
  27. data/lib/brakeman/checks/check_mass_assignment.rb +143 -0
  28. data/lib/brakeman/checks/check_model_attr_accessible.rb +48 -0
  29. data/lib/brakeman/checks/check_model_attributes.rb +118 -0
  30. data/lib/brakeman/checks/check_model_serialize.rb +66 -0
  31. data/lib/{checks → brakeman/checks}/check_nested_attributes.rb +10 -6
  32. data/lib/brakeman/checks/check_quote_table_name.rb +40 -0
  33. data/lib/brakeman/checks/check_redirect.rb +177 -0
  34. data/lib/brakeman/checks/check_render.rb +62 -0
  35. data/lib/brakeman/checks/check_response_splitting.rb +21 -0
  36. data/lib/brakeman/checks/check_safe_buffer_manipulation.rb +31 -0
  37. data/lib/brakeman/checks/check_sanitize_methods.rb +54 -0
  38. data/lib/brakeman/checks/check_select_tag.rb +60 -0
  39. data/lib/brakeman/checks/check_select_vulnerability.rb +58 -0
  40. data/lib/brakeman/checks/check_send.rb +35 -0
  41. data/lib/brakeman/checks/check_send_file.rb +19 -0
  42. data/lib/brakeman/checks/check_session_settings.rb +145 -0
  43. data/lib/brakeman/checks/check_single_quotes.rb +101 -0
  44. data/lib/brakeman/checks/check_skip_before_filter.rb +62 -0
  45. data/lib/brakeman/checks/check_sql.rb +577 -0
  46. data/lib/brakeman/checks/check_strip_tags.rb +64 -0
  47. data/lib/brakeman/checks/check_symbol_dos.rb +67 -0
  48. data/lib/brakeman/checks/check_translate_bug.rb +45 -0
  49. data/lib/brakeman/checks/check_unsafe_reflection.rb +51 -0
  50. data/lib/brakeman/checks/check_validation_regex.rb +88 -0
  51. data/lib/brakeman/checks/check_without_protection.rb +64 -0
  52. data/lib/brakeman/checks/check_yaml_parsing.rb +121 -0
  53. data/lib/brakeman/differ.rb +66 -0
  54. data/lib/{format → brakeman/format}/style.css +28 -0
  55. data/lib/brakeman/options.rb +256 -0
  56. data/lib/brakeman/parsers/rails2_erubis.rb +6 -0
  57. data/lib/brakeman/parsers/rails2_xss_plugin_erubis.rb +48 -0
  58. data/lib/{scanner_erubis.rb → brakeman/parsers/rails3_erubis.rb} +8 -21
  59. data/lib/brakeman/processor.rb +102 -0
  60. data/lib/brakeman/processors/alias_processor.rb +780 -0
  61. data/lib/{processors → brakeman/processors}/base_processor.rb +90 -74
  62. data/lib/brakeman/processors/config_processor.rb +14 -0
  63. data/lib/brakeman/processors/controller_alias_processor.rb +334 -0
  64. data/lib/brakeman/processors/controller_processor.rb +265 -0
  65. data/lib/{processors → brakeman/processors}/erb_template_processor.rb +21 -19
  66. data/lib/brakeman/processors/erubis_template_processor.rb +96 -0
  67. data/lib/brakeman/processors/gem_processor.rb +59 -0
  68. data/lib/{processors → brakeman/processors}/haml_template_processor.rb +26 -21
  69. data/lib/brakeman/processors/lib/find_all_calls.rb +185 -0
  70. data/lib/{processors → brakeman/processors}/lib/find_call.rb +23 -28
  71. data/lib/brakeman/processors/lib/find_return_value.rb +134 -0
  72. data/lib/brakeman/processors/lib/processor_helper.rb +82 -0
  73. data/lib/{processors/config_processor.rb → brakeman/processors/lib/rails2_config_processor.rb} +32 -35
  74. data/lib/{processors → brakeman/processors}/lib/rails2_route_processor.rb +60 -52
  75. data/lib/brakeman/processors/lib/rails3_config_processor.rb +129 -0
  76. data/lib/brakeman/processors/lib/rails3_route_processor.rb +282 -0
  77. data/lib/{processors → brakeman/processors}/lib/render_helper.rb +54 -20
  78. data/lib/brakeman/processors/lib/route_helper.rb +62 -0
  79. data/lib/{processors → brakeman/processors}/library_processor.rb +24 -17
  80. data/lib/{processors → brakeman/processors}/model_processor.rb +46 -22
  81. data/lib/{processors → brakeman/processors}/output_processor.rb +34 -40
  82. data/lib/brakeman/processors/route_processor.rb +17 -0
  83. data/lib/brakeman/processors/slim_template_processor.rb +113 -0
  84. data/lib/brakeman/processors/template_alias_processor.rb +120 -0
  85. data/lib/{processors → brakeman/processors}/template_processor.rb +10 -7
  86. data/lib/brakeman/report.rb +68 -0
  87. data/lib/brakeman/report/ignore/config.rb +130 -0
  88. data/lib/brakeman/report/ignore/interactive.rb +311 -0
  89. data/lib/brakeman/report/initializers/faster_csv.rb +7 -0
  90. data/lib/brakeman/report/initializers/multi_json.rb +29 -0
  91. data/lib/brakeman/report/renderer.rb +24 -0
  92. data/lib/brakeman/report/report_base.rb +279 -0
  93. data/lib/brakeman/report/report_csv.rb +56 -0
  94. data/lib/brakeman/report/report_hash.rb +22 -0
  95. data/lib/brakeman/report/report_html.rb +203 -0
  96. data/lib/brakeman/report/report_json.rb +46 -0
  97. data/lib/brakeman/report/report_table.rb +109 -0
  98. data/lib/brakeman/report/report_tabs.rb +17 -0
  99. data/lib/brakeman/report/templates/controller_overview.html.erb +18 -0
  100. data/lib/brakeman/report/templates/controller_warnings.html.erb +17 -0
  101. data/lib/brakeman/report/templates/error_overview.html.erb +25 -0
  102. data/lib/brakeman/report/templates/header.html.erb +44 -0
  103. data/lib/brakeman/report/templates/ignored_warnings.html.erb +21 -0
  104. data/lib/brakeman/report/templates/model_warnings.html.erb +17 -0
  105. data/lib/brakeman/report/templates/overview.html.erb +34 -0
  106. data/lib/brakeman/report/templates/security_warnings.html.erb +19 -0
  107. data/lib/brakeman/report/templates/template_overview.html.erb +17 -0
  108. data/lib/brakeman/report/templates/view_warnings.html.erb +30 -0
  109. data/lib/brakeman/report/templates/warning_overview.html.erb +13 -0
  110. data/lib/brakeman/rescanner.rb +446 -0
  111. data/lib/brakeman/scanner.rb +362 -0
  112. data/lib/brakeman/tracker.rb +296 -0
  113. data/lib/brakeman/util.rb +413 -0
  114. data/lib/brakeman/version.rb +3 -0
  115. data/lib/brakeman/warning.rb +217 -0
  116. data/lib/brakeman/warning_codes.rb +68 -0
  117. data/lib/ruby_parser/bm_sexp.rb +562 -0
  118. data/lib/ruby_parser/bm_sexp_processor.rb +230 -0
  119. metadata +152 -66
  120. data/lib/checks.rb +0 -71
  121. data/lib/checks/base_check.rb +0 -357
  122. data/lib/checks/check_cross_site_scripting.rb +0 -336
  123. data/lib/checks/check_evaluation.rb +0 -27
  124. data/lib/checks/check_execute.rb +0 -110
  125. data/lib/checks/check_file_access.rb +0 -46
  126. data/lib/checks/check_forgery_setting.rb +0 -42
  127. data/lib/checks/check_mass_assignment.rb +0 -74
  128. data/lib/checks/check_model_attributes.rb +0 -36
  129. data/lib/checks/check_redirect.rb +0 -98
  130. data/lib/checks/check_render.rb +0 -65
  131. data/lib/checks/check_send_file.rb +0 -15
  132. data/lib/checks/check_session_settings.rb +0 -79
  133. data/lib/checks/check_sql.rb +0 -146
  134. data/lib/checks/check_validation_regex.rb +0 -60
  135. data/lib/processor.rb +0 -86
  136. data/lib/processors/alias_processor.rb +0 -384
  137. data/lib/processors/controller_alias_processor.rb +0 -237
  138. data/lib/processors/controller_processor.rb +0 -202
  139. data/lib/processors/erubis_template_processor.rb +0 -85
  140. data/lib/processors/lib/find_model_call.rb +0 -39
  141. data/lib/processors/lib/processor_helper.rb +0 -36
  142. data/lib/processors/lib/rails3_route_processor.rb +0 -184
  143. data/lib/processors/lib/route_helper.rb +0 -34
  144. data/lib/processors/params_processor.rb +0 -77
  145. data/lib/processors/route_processor.rb +0 -11
  146. data/lib/processors/template_alias_processor.rb +0 -86
  147. data/lib/report.rb +0 -680
  148. data/lib/scanner.rb +0 -227
  149. data/lib/tracker.rb +0 -144
  150. data/lib/util.rb +0 -141
  151. data/lib/version.rb +0 -1
  152. data/lib/warning.rb +0 -99
@@ -0,0 +1,68 @@
1
+ module Brakeman::WarningCodes
2
+ Codes = {
3
+ :sql_injection => 0,
4
+ :sql_injection_limit_offset => 1,
5
+ :cross_site_scripting => 2,
6
+ :xss_link_to => 3,
7
+ :xss_link_to_href => 4,
8
+ :xss_to_json => 5,
9
+ :csrf_protection_disabled => 6,
10
+ :csrf_protection_missing => 7,
11
+ :csrf_blacklist => 8,
12
+ :basic_auth_password => 9,
13
+ :auth_blacklist => 10,
14
+ :all_default_routes => 11,
15
+ :controller_default_routes => 12,
16
+ :code_eval => 13,
17
+ :command_injection => 14,
18
+ :dynamic_render_path => 15,
19
+ :file_access => 16,
20
+ :mass_assign_call => 17,
21
+ :open_redirect => 18,
22
+ :no_attr_accessible => 19,
23
+ :attr_protected_used => 20,
24
+ :safe_buffer_vuln => 21,
25
+ :select_options_vuln => 22,
26
+ :dangerous_send => 23,
27
+ :unsafe_constantize => 24,
28
+ :unsafe_deserialize => 25,
29
+ :http_cookies => 26,
30
+ :secure_cookies => 27,
31
+ :translate_vuln => 28,
32
+ :session_secret => 29,
33
+ :validation_regex => 30,
34
+ :CVE_2010_3933 => 31,
35
+ :CVE_2011_0446 => 32,
36
+ :CVE_2011_0447 => 33,
37
+ :CVE_2011_2929 => 34,
38
+ :CVE_2011_2930 => 35,
39
+ :CVE_2011_2931 => 36,
40
+ :CVE_2011_3186 => 37,
41
+ :CVE_2012_2660 => 38,
42
+ :CVE_2012_2661 => 39,
43
+ :CVE_2012_2695 => 40,
44
+ :CVE_2012_2931 => 41,
45
+ :CVE_2012_3424 => 42,
46
+ :CVE_2012_3463 => 43,
47
+ :CVE_2012_3464 => 44,
48
+ :CVE_2012_3465 => 45,
49
+ :CVE_2012_5664 => 46,
50
+ :CVE_2013_0155 => 47,
51
+ :CVE_2013_0156 => 48,
52
+ :CVE_2013_0269 => 49,
53
+ :CVE_2013_0277 => 50,
54
+ :CVE_2013_0276 => 51,
55
+ :CVE_2013_0333 => 52,
56
+ :xss_content_tag => 53,
57
+ :mass_assign_without_protection => 54,
58
+ :CVE_2013_1854 => 55,
59
+ :CVE_2013_1855 => 56,
60
+ :CVE_2013_1856 => 57,
61
+ :CVE_2013_1857 => 58,
62
+ :unsafe_symbol_creation => 59
63
+ }
64
+
65
+ def self.code name
66
+ Codes[name]
67
+ end
68
+ end
@@ -0,0 +1,562 @@
1
+ #Sexp changes from ruby_parser
2
+ #and some changes for caching hash value and tracking 'original' line number
3
+ #of a Sexp.
4
+ class Sexp
5
+ attr_reader :paren
6
+ attr_accessor :original_line, :or_depth
7
+ ASSIGNMENT_BOOL = [:gasgn, :iasgn, :lasgn, :cvdecl, :cdecl, :or, :and, :colon2]
8
+
9
+ def method_missing name, *args
10
+ #Brakeman does not use this functionality,
11
+ #so overriding it to raise a NoMethodError.
12
+ #
13
+ #The original functionality calls find_node and optionally
14
+ #deletes the node if found.
15
+ raise NoMethodError.new("No method '#{name}' for Sexp", name, args)
16
+ end
17
+
18
+ #Create clone of Sexp and nested Sexps but not their non-Sexp contents.
19
+ #If a line number is provided, also sets line/original_line on all Sexps.
20
+ def deep_clone line = nil
21
+ s = Sexp.new
22
+
23
+ self.each do |e|
24
+ if e.is_a? Sexp
25
+ s << e.deep_clone(line)
26
+ else
27
+ s << e
28
+ end
29
+ end
30
+
31
+ if line
32
+ s.original_line = self.original_line || self.line
33
+ s.line(line)
34
+ else
35
+ s.original_line = self.original_line
36
+ s.line(self.line)
37
+ end
38
+
39
+ s
40
+ end
41
+
42
+ def paren
43
+ @paren ||= false
44
+ end
45
+
46
+ def value
47
+ raise WrongSexpError, "Sexp#value called on multi-item Sexp", caller[1..-1] if size > 2
48
+ last
49
+ end
50
+
51
+ def value= exp
52
+ raise WrongSexpError, "Sexp#value= called on multi-item Sexp", caller[1..-1] if size > 2
53
+ @my_hash_value = nil
54
+ self[1] = exp
55
+ end
56
+
57
+ def second
58
+ self[1]
59
+ end
60
+
61
+ def to_sym
62
+ self.value.to_sym
63
+ end
64
+
65
+ def node_type= type
66
+ @my_hash_value = nil
67
+ self[0] = type
68
+ end
69
+
70
+ #Join self and exp into an :or Sexp.
71
+ #Sets or_depth.
72
+ #Used for combining "branched" values in AliasProcessor.
73
+ def combine exp, line = nil
74
+ combined = Sexp.new(:or, self, exp).line(line || -2)
75
+
76
+ combined.or_depth = [self.or_depth, exp.or_depth].compact.reduce(0, :+) + 1
77
+
78
+ combined
79
+ end
80
+
81
+ alias :node_type :sexp_type
82
+ alias :values :sexp_body # TODO: retire
83
+
84
+ alias :old_push :<<
85
+ alias :old_compact :compact
86
+ alias :old_fara :find_and_replace_all
87
+ alias :old_find_node :find_node
88
+
89
+ def << arg
90
+ @my_hash_value = nil
91
+ old_push arg
92
+ end
93
+
94
+ def hash
95
+ #There still seems to be some instances in which the hash of the
96
+ #Sexp changes, but I have not found what method call is doing it.
97
+ #Of course, Sexp is subclasses from Array, so who knows what might
98
+ #be going on.
99
+ @my_hash_value ||= super
100
+ end
101
+
102
+ def compact
103
+ @my_hash_value = nil
104
+ old_compact
105
+ end
106
+
107
+ def find_and_replace_all *args
108
+ @my_hash_value = nil
109
+ old_fara(*args)
110
+ end
111
+
112
+ def find_node *args
113
+ @my_hash_value = nil
114
+ old_find_node(*args)
115
+ end
116
+
117
+ #Iterates over the Sexps in an Sexp, skipping values that are not
118
+ #an Sexp.
119
+ def each_sexp
120
+ self.each do |e|
121
+ yield e if Sexp === e
122
+ end
123
+ end
124
+
125
+ #Raise a WrongSexpError if the nodes type does not match one of the expected
126
+ #types.
127
+ def expect *types
128
+ unless types.include? self.node_type
129
+ raise WrongSexpError, "Expected #{types.join ' or '} but given #{self.inspect}", caller[1..-1]
130
+ end
131
+ end
132
+
133
+ #Returns target of a method call:
134
+ #
135
+ #s(:call, s(:call, nil, :x, s(:arglist)), :y, s(:arglist, s(:lit, 1)))
136
+ # ^-----------target-----------^
137
+ def target
138
+ expect :call, :attrasgn
139
+ self[1]
140
+ end
141
+
142
+ #Sets the target of a method call:
143
+ def target= exp
144
+ expect :call, :attrasgn
145
+ @my_hash_value = nil
146
+ self[1] = exp
147
+ end
148
+
149
+ #Returns method of a method call:
150
+ #
151
+ #s(:call, s(:call, nil, :x, s(:arglist)), :y, s(:arglist, s(:lit, 1)))
152
+ # ^- method
153
+ def method
154
+ expect :call, :attrasgn, :super, :zsuper, :result
155
+
156
+ case self.node_type
157
+ when :call, :attrasgn
158
+ self[2]
159
+ when :super, :zsuper
160
+ :super
161
+ when :result
162
+ self.last
163
+ end
164
+ end
165
+
166
+ #Sets the arglist in a method call.
167
+ def arglist= exp
168
+ expect :call, :attrasgn
169
+ @my_hash_value = nil
170
+ start_index = 3
171
+
172
+ if exp.is_a? Sexp and exp.node_type == :arglist
173
+ exp = exp[1..-1]
174
+ end
175
+
176
+ exp.each_with_index do |e, i|
177
+ self[start_index + i] = e
178
+ end
179
+ end
180
+
181
+ def set_args *exp
182
+ self.arglist = exp
183
+ end
184
+
185
+ #Returns arglist for method call. This differs from Sexp#args, as Sexp#args
186
+ #does not return a 'real' Sexp (it does not have a node type) but
187
+ #Sexp#arglist returns a s(:arglist, ...)
188
+ #
189
+ # s(:call, s(:call, nil, :x, s(:arglist)), :y, s(:arglist, s(:lit, 1), s(:lit, 2)))
190
+ # ^------------ arglist ------------^
191
+ def arglist
192
+ expect :call, :attrasgn, :super, :zsuper
193
+
194
+ case self.node_type
195
+ when :call, :attrasgn
196
+ self[3..-1].unshift :arglist
197
+ when :super, :zsuper
198
+ if self[1]
199
+ self[1..-1].unshift :arglist
200
+ else
201
+ Sexp.new(:arglist)
202
+ end
203
+ end
204
+ end
205
+
206
+ #Returns arguments of a method call. This will be an 'untyped' Sexp.
207
+ #
208
+ # s(:call, s(:call, nil, :x, s(:arglist)), :y, s(:arglist, s(:lit, 1), s(:lit, 2)))
209
+ # ^--------args--------^
210
+ def args
211
+ expect :call, :attrasgn, :super, :zsuper
212
+
213
+ case self.node_type
214
+ when :call, :attrasgn
215
+ if self[3]
216
+ self[3..-1]
217
+ else
218
+ Sexp.new
219
+ end
220
+ when :super, :zsuper
221
+ if self[1]
222
+ self[1..-1]
223
+ else
224
+ Sexp.new
225
+ end
226
+ end
227
+ end
228
+
229
+ def each_arg replace = false
230
+ expect :call, :attrasgn, :super, :zsuper
231
+ range = nil
232
+
233
+ case self.node_type
234
+ when :call, :attrasgn
235
+ if self[3]
236
+ range = (3...self.length)
237
+ end
238
+ when :super, :zsuper
239
+ if self[1]
240
+ range = (1...self.length)
241
+ end
242
+ end
243
+
244
+ if range
245
+ range.each do |i|
246
+ res = yield self[i]
247
+ self[i] = res if replace
248
+ end
249
+ end
250
+
251
+ self
252
+ end
253
+
254
+ def each_arg! &block
255
+ @my_hash_value = nil
256
+ self.each_arg true, &block
257
+ end
258
+
259
+ #Returns first argument of a method call.
260
+ def first_arg
261
+ expect :call, :attrasgn
262
+ self[3]
263
+ end
264
+
265
+ #Sets first argument of a method call.
266
+ def first_arg= exp
267
+ expect :call, :attrasgn
268
+ @my_hash_value = nil
269
+ self[3] = exp
270
+ end
271
+
272
+ #Returns second argument of a method call.
273
+ def second_arg
274
+ expect :call, :attrasgn
275
+ self[4]
276
+ end
277
+
278
+ #Sets second argument of a method call.
279
+ def second_arg= exp
280
+ expect :call, :attrasgn
281
+ @my_hash_value = nil
282
+ self[4] = exp
283
+ end
284
+
285
+ def third_arg
286
+ expect :call, :attrasgn
287
+ self[5]
288
+ end
289
+
290
+ def third_arg= exp
291
+ expect :call, :attrasgn
292
+ @my_hash_value = nil
293
+ self[5] = exp
294
+ end
295
+
296
+ def last_arg
297
+ expect :call, :attrasgn
298
+
299
+ if self[3]
300
+ self[-1]
301
+ else
302
+ nil
303
+ end
304
+ end
305
+
306
+ #Returns condition of an if expression:
307
+ #
308
+ # s(:if,
309
+ # s(:lvar, :condition), <-- condition
310
+ # s(:lvar, :then_val),
311
+ # s(:lvar, :else_val)))
312
+ def condition
313
+ expect :if
314
+ self[1]
315
+ end
316
+
317
+ #Returns 'then' clause of an if expression:
318
+ #
319
+ # s(:if,
320
+ # s(:lvar, :condition),
321
+ # s(:lvar, :then_val), <-- then clause
322
+ # s(:lvar, :else_val)))
323
+ def then_clause
324
+ expect :if
325
+ self[2]
326
+ end
327
+
328
+ #Returns 'else' clause of an if expression:
329
+ #
330
+ # s(:if,
331
+ # s(:lvar, :condition),
332
+ # s(:lvar, :then_val),
333
+ # s(:lvar, :else_val)))
334
+ # ^---else caluse---^
335
+ def else_clause
336
+ expect :if
337
+ self[3]
338
+ end
339
+
340
+ #Method call associated with a block:
341
+ #
342
+ # s(:iter,
343
+ # s(:call, nil, :x, s(:arglist)), <- block_call
344
+ # s(:lasgn, :y),
345
+ # s(:block, s(:lvar, :y), s(:call, nil, :z, s(:arglist))))
346
+ def block_call
347
+ expect :iter, :call_with_block
348
+ self[1]
349
+ end
350
+
351
+ #Returns block of a call with a block.
352
+ #Could be a single expression or a block:
353
+ #
354
+ # s(:iter,
355
+ # s(:call, nil, :x, s(:arglist)),
356
+ # s(:lasgn, :y),
357
+ # s(:block, s(:lvar, :y), s(:call, nil, :z, s(:arglist))))
358
+ # ^-------------------- block --------------------------^
359
+ def block delete = nil
360
+ unless delete.nil? #this is from RubyParser
361
+ return find_node :block, delete
362
+ end
363
+
364
+ expect :iter, :call_with_block, :scope, :resbody
365
+
366
+ case self.node_type
367
+ when :iter, :call_with_block
368
+ self[3]
369
+ when :scope
370
+ self[1]
371
+ when :resbody
372
+ #This is for Ruby2Ruby ONLY
373
+ find_node :block
374
+ end
375
+ end
376
+
377
+ #Returns parameters for a block
378
+ #
379
+ # s(:iter,
380
+ # s(:call, nil, :x, s(:arglist)),
381
+ # s(:lasgn, :y), <- block_args
382
+ # s(:call, nil, :p, s(:arglist, s(:lvar, :y))))
383
+ def block_args
384
+ expect :iter, :call_with_block
385
+ if self[2] == 0 # ?! See https://github.com/presidentbeef/brakeman/issues/331
386
+ return Sexp.new(:args)
387
+ else
388
+ self[2]
389
+ end
390
+ end
391
+
392
+ def first_param
393
+ expect :args
394
+ self[1]
395
+ end
396
+
397
+ #Returns the left hand side of assignment or boolean:
398
+ #
399
+ # s(:lasgn, :x, s(:lit, 1))
400
+ # ^--lhs
401
+ def lhs
402
+ expect *ASSIGNMENT_BOOL
403
+ self[1]
404
+ end
405
+
406
+ #Sets the left hand side of assignment or boolean.
407
+ def lhs= exp
408
+ expect *ASSIGNMENT_BOOL
409
+ self[1] = exp
410
+ end
411
+
412
+ #Returns right side (value) of assignment or boolean:
413
+ #
414
+ # s(:lasgn, :x, s(:lit, 1))
415
+ # ^--rhs---^
416
+ def rhs
417
+ expect *ASSIGNMENT_BOOL
418
+ self[2]
419
+ end
420
+
421
+ #Sets the right hand side of assignment or boolean.
422
+ def rhs= exp
423
+ expect *ASSIGNMENT_BOOL
424
+ self[2] = exp
425
+ end
426
+
427
+ #Returns name of method being defined in a method definition.
428
+ def method_name
429
+ expect :defn, :defs, :methdef, :selfdef
430
+
431
+ case self.node_type
432
+ when :defn, :methdef
433
+ self[1]
434
+ when :defs, :selfdef
435
+ self[2]
436
+ end
437
+ end
438
+
439
+ def formal_args
440
+ expect :defn, :defs, :methdef, :selfdef
441
+
442
+ case self.node_type
443
+ when :defn, :methdef
444
+ self[2]
445
+ when :defs, :selfdef
446
+ self[3]
447
+ end
448
+ end
449
+
450
+ #Sets body, which is now a complicated process because the body is no longer
451
+ #a separate Sexp, but just a list of Sexps.
452
+ def body= exp
453
+ expect :defn, :defs, :methdef, :selfdef, :class, :module
454
+ @my_hash_value = nil
455
+
456
+ case self.node_type
457
+ when :defn, :methdef, :class
458
+ index = 3
459
+ when :defs, :selfdef
460
+ index = 4
461
+ when :module
462
+ index = 2
463
+ end
464
+
465
+ self.slice!(index..-1) #Remove old body
466
+
467
+ #Insert new body
468
+ exp.each do |e|
469
+ self[index] = e
470
+ index += 1
471
+ end
472
+ end
473
+
474
+ #Returns body of a method definition, class, or module.
475
+ #This will be an untyped Sexp containing a list of Sexps from the body.
476
+ def body
477
+ expect :defn, :defs, :methdef, :selfdef, :class, :module
478
+
479
+ case self.node_type
480
+ when :defn, :methdef, :class
481
+ self[3..-1]
482
+ when :defs, :selfdef
483
+ self[4..-1]
484
+ when :module
485
+ self[2..-1]
486
+ end
487
+ end
488
+
489
+ #Like Sexp#body, except the returned Sexp is of type :rlist
490
+ #instead of untyped.
491
+ def body_list
492
+ self.body.unshift :rlist
493
+ end
494
+
495
+ def render_type
496
+ expect :render
497
+ self[1]
498
+ end
499
+
500
+ def class_name
501
+ expect :class, :module
502
+ self[1]
503
+ end
504
+
505
+ alias module_name class_name
506
+
507
+ def parent_name
508
+ expect :class
509
+ self[2]
510
+ end
511
+
512
+ #Returns the call Sexp in a result returned from FindCall
513
+ def call
514
+ expect :result
515
+
516
+ self.last
517
+ end
518
+
519
+ #Returns the module the call is inside
520
+ def module
521
+ expect :result
522
+
523
+ self[1]
524
+ end
525
+
526
+ #Return the class the call is inside
527
+ def result_class
528
+ expect :result
529
+
530
+ self[2]
531
+ end
532
+ end
533
+
534
+ #Invalidate hash cache if the Sexp changes
535
+ [:[]=, :clear, :collect!, :compact!, :concat, :delete, :delete_at,
536
+ :delete_if, :drop, :drop_while, :fill, :flatten!, :replace, :insert,
537
+ :keep_if, :map!, :pop, :push, :reject!, :replace, :reverse!, :rotate!,
538
+ :select!, :shift, :shuffle!, :slice!, :sort!, :sort_by!, :transpose,
539
+ :uniq!, :unshift].each do |method|
540
+
541
+ Sexp.class_eval <<-RUBY
542
+ def #{method} *args
543
+ @my_hash_value = nil
544
+ super
545
+ end
546
+ RUBY
547
+ end
548
+
549
+ #Methods used by RubyParser which would normally go through method_missing but
550
+ #we don't want that to happen because it hides Brakeman errors
551
+ [:resbody, :lasgn, :iasgn, :splat].each do |method|
552
+ Sexp.class_eval <<-RUBY
553
+ def #{method} delete = false
554
+ if delete
555
+ @my_hash_value = false
556
+ end
557
+ find_node :#{method}, delete
558
+ end
559
+ RUBY
560
+ end
561
+
562
+ class WrongSexpError < RuntimeError; end