brakeman 1.7.1 → 1.8.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 (57) hide show
  1. data/bin/brakeman +3 -0
  2. data/lib/brakeman.rb +2 -0
  3. data/lib/brakeman/brakeman.rake +4 -3
  4. data/lib/brakeman/checks/base_check.rb +40 -37
  5. data/lib/brakeman/checks/check_basic_auth.rb +3 -3
  6. data/lib/brakeman/checks/check_content_tag.rb +179 -0
  7. data/lib/brakeman/checks/check_cross_site_scripting.rb +41 -17
  8. data/lib/brakeman/checks/check_execute.rb +1 -1
  9. data/lib/brakeman/checks/check_file_access.rb +2 -2
  10. data/lib/brakeman/checks/check_link_to.rb +9 -7
  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 +6 -5
  14. data/lib/brakeman/checks/check_redirect.rb +18 -17
  15. data/lib/brakeman/checks/check_render.rb +3 -1
  16. data/lib/brakeman/checks/check_select_tag.rb +2 -2
  17. data/lib/brakeman/checks/check_select_vulnerability.rb +3 -3
  18. data/lib/brakeman/checks/check_send.rb +3 -3
  19. data/lib/brakeman/checks/check_session_settings.rb +5 -5
  20. data/lib/brakeman/checks/check_single_quotes.rb +8 -8
  21. data/lib/brakeman/checks/check_skip_before_filter.rb +2 -2
  22. data/lib/brakeman/checks/check_sql.rb +36 -39
  23. data/lib/brakeman/checks/check_validation_regex.rb +3 -3
  24. data/lib/brakeman/checks/check_without_protection.rb +2 -2
  25. data/lib/brakeman/format/style.css +15 -0
  26. data/lib/brakeman/options.rb +4 -0
  27. data/lib/brakeman/processor.rb +1 -1
  28. data/lib/brakeman/processors/alias_processor.rb +63 -61
  29. data/lib/brakeman/processors/base_processor.rb +31 -45
  30. data/lib/brakeman/processors/controller_alias_processor.rb +11 -9
  31. data/lib/brakeman/processors/controller_processor.rb +26 -25
  32. data/lib/brakeman/processors/erb_template_processor.rb +12 -12
  33. data/lib/brakeman/processors/erubis_template_processor.rb +19 -17
  34. data/lib/brakeman/processors/gem_processor.rb +5 -5
  35. data/lib/brakeman/processors/haml_template_processor.rb +16 -12
  36. data/lib/brakeman/processors/lib/find_all_calls.rb +11 -17
  37. data/lib/brakeman/processors/lib/find_call.rb +16 -23
  38. data/lib/brakeman/processors/lib/processor_helper.rb +11 -5
  39. data/lib/brakeman/processors/lib/rails2_config_processor.rb +21 -20
  40. data/lib/brakeman/processors/lib/rails2_route_processor.rb +38 -34
  41. data/lib/brakeman/processors/lib/rails3_config_processor.rb +17 -17
  42. data/lib/brakeman/processors/lib/rails3_route_processor.rb +42 -40
  43. data/lib/brakeman/processors/lib/render_helper.rb +6 -6
  44. data/lib/brakeman/processors/lib/route_helper.rb +1 -1
  45. data/lib/brakeman/processors/library_processor.rb +11 -11
  46. data/lib/brakeman/processors/model_processor.rb +18 -16
  47. data/lib/brakeman/processors/template_alias_processor.rb +36 -29
  48. data/lib/brakeman/processors/template_processor.rb +4 -4
  49. data/lib/brakeman/report.rb +23 -4
  50. data/lib/brakeman/templates/error_overview.html.erb +9 -1
  51. data/lib/brakeman/templates/view_warnings.html.erb +16 -3
  52. data/lib/brakeman/tracker.rb +3 -0
  53. data/lib/brakeman/util.rb +5 -1
  54. data/lib/brakeman/version.rb +1 -1
  55. data/lib/brakeman/warning.rb +1 -1
  56. data/lib/ruby_parser/bm_sexp.rb +302 -2
  57. metadata +6 -5
@@ -29,9 +29,9 @@ class Brakeman::Rails3ConfigProcessor < Brakeman::BaseProcessor
29
29
 
30
30
  #Look for MyApp::Application.configure do ... end
31
31
  def process_iter exp
32
- if node_type?(exp[1][1], :colon2) and exp[1][1][2] == :Application
32
+ if node_type?(exp.block_call.target, :colon2) and exp.block_call.method == :Application
33
33
  @inside_config = true
34
- process exp[-1] if sexp? exp[-1]
34
+ process exp.body if sexp? exp.body
35
35
  @inside_config = false
36
36
  end
37
37
 
@@ -40,9 +40,9 @@ class Brakeman::Rails3ConfigProcessor < Brakeman::BaseProcessor
40
40
 
41
41
  #Look for class Application < Rails::Application
42
42
  def process_class exp
43
- if exp[1] == :Application
43
+ if exp.class_name == :Application
44
44
  @inside_config = true
45
- process exp[-1] if sexp? exp[-1]
45
+ process exp.body if sexp? exp.body
46
46
  @inside_config = false
47
47
  end
48
48
 
@@ -53,14 +53,14 @@ class Brakeman::Rails3ConfigProcessor < Brakeman::BaseProcessor
53
53
  def process_attrasgn exp
54
54
  return exp unless @inside_config
55
55
 
56
- if exp[1] == Brakeman::RAILS_CONFIG
56
+ if exp.target == Brakeman::RAILS_CONFIG
57
57
  #Get rid of '=' at end
58
- attribute = exp[2].to_s[0..-2].to_sym
59
- if exp[3].length > 2
58
+ attribute = exp.method.to_s[0..-2].to_sym
59
+ if exp.args.length > 1
60
60
  #Multiple arguments?...not sure if this will ever happen
61
- @tracker.config[:rails][attribute] = exp[3][1..-1]
61
+ @tracker.config[:rails][attribute] = exp.args
62
62
  else
63
- @tracker.config[:rails][attribute] = exp[3][1]
63
+ @tracker.config[:rails][attribute] = exp.first_arg
64
64
  end
65
65
  elsif include_rails_config? exp
66
66
  options = get_rails_config exp
@@ -70,7 +70,7 @@ class Brakeman::Rails3ConfigProcessor < Brakeman::BaseProcessor
70
70
  level = level[o]
71
71
  end
72
72
 
73
- level[options.last] = exp[3][1]
73
+ level[options.last] = exp.first_arg
74
74
  end
75
75
 
76
76
  exp
@@ -78,9 +78,9 @@ class Brakeman::Rails3ConfigProcessor < Brakeman::BaseProcessor
78
78
 
79
79
  #Check if an expression includes a call to set Rails config
80
80
  def include_rails_config? exp
81
- target = exp[1]
81
+ target = exp.target
82
82
  if call? target
83
- if target[1] == Brakeman::RAILS_CONFIG
83
+ if target.target == Brakeman::RAILS_CONFIG
84
84
  true
85
85
  else
86
86
  include_rails_config? target
@@ -101,13 +101,13 @@ class Brakeman::Rails3ConfigProcessor < Brakeman::BaseProcessor
101
101
  # [:action_controller, :session_store]
102
102
  def get_rails_config exp
103
103
  if node_type? exp, :attrasgn
104
- attribute = exp[2].to_s[0..-2].to_sym
105
- get_rails_config(exp[1]) << attribute
104
+ attribute = exp.method.to_s[0..-2].to_sym
105
+ get_rails_config(exp.target) << attribute
106
106
  elsif call? exp
107
- if exp[1] == Brakeman::RAILS_CONFIG
108
- [exp[2]]
107
+ if exp.target == Brakeman::RAILS_CONFIG
108
+ [exp.method]
109
109
  else
110
- get_rails_config(exp[1]) << exp[2]
110
+ get_rails_config(exp.target) << exp.method
111
111
  end
112
112
  else
113
113
  raise "WHAT"
@@ -22,7 +22,7 @@ class Brakeman::Rails3RoutesProcessor < Brakeman::BaseProcessor
22
22
  end
23
23
 
24
24
  def process_call exp
25
- case exp[2]
25
+ case exp.method
26
26
  when :resources
27
27
  process_resources exp
28
28
  when :resource
@@ -41,7 +41,7 @@ class Brakeman::Rails3RoutesProcessor < Brakeman::BaseProcessor
41
41
  end
42
42
 
43
43
  def process_iter exp
44
- case exp[1][2]
44
+ case exp.block_call.method
45
45
  when :namespace
46
46
  process_namespace exp
47
47
  when :resource
@@ -58,8 +58,8 @@ class Brakeman::Rails3RoutesProcessor < Brakeman::BaseProcessor
58
58
  end
59
59
 
60
60
  def process_namespace exp
61
- name = exp[1][3][1][1]
62
- block = exp[3]
61
+ name = exp.block_call.first_arg.value
62
+ block = exp.block
63
63
 
64
64
  @prefix << camelize(name)
65
65
 
@@ -70,10 +70,11 @@ class Brakeman::Rails3RoutesProcessor < Brakeman::BaseProcessor
70
70
  exp
71
71
  end
72
72
 
73
+ #TODO: Need test for this
73
74
  def process_root exp
74
- args = exp[3][1..-1]
75
+ args = exp.args
75
76
 
76
- if value = hash_access(args[0], :to)
77
+ if value = hash_access(args.first, :to)
77
78
  if string? value
78
79
  add_route_from_string value
79
80
  end
@@ -83,17 +84,17 @@ class Brakeman::Rails3RoutesProcessor < Brakeman::BaseProcessor
83
84
  end
84
85
 
85
86
  def process_match exp
86
- args = exp[3][1..-1]
87
+ args = exp.args
87
88
 
88
89
  #Check if there is an unrestricted action parameter
89
90
  action_variable = false
90
91
 
91
- if string? args[0]
92
- matcher = args[0][1]
92
+ if string? args.first
93
+ matcher = args.first.value
93
94
 
94
95
  if matcher == ':controller(/:action(/:id(.:format)))' or
95
96
  matcher.include? ':controller' and matcher.include? ':action' #Default routes
96
- @tracker.routes[:allow_all_actions] = args[0]
97
+ @tracker.routes[:allow_all_actions] = args.first
97
98
  return exp
98
99
  elsif matcher.include? ':action'
99
100
  action_variable = true
@@ -102,16 +103,16 @@ class Brakeman::Rails3RoutesProcessor < Brakeman::BaseProcessor
102
103
  end
103
104
  end
104
105
 
105
- if hash? args[-1]
106
- hash_iterate args[-1] do |k, v|
106
+ if hash? args.last
107
+ hash_iterate args.last do |k, v|
107
108
  if string? k
108
109
  if string? v
109
- add_route_from_string v[1]
110
+ add_route_from_string v
110
111
  elsif in_controller_block? and symbol? v
111
112
  add_route v
112
113
  end
113
114
  elsif symbol? k
114
- case k[1]
115
+ case k.value
115
116
  when :action
116
117
  if string? v
117
118
  add_route_from_string v
@@ -152,31 +153,32 @@ class Brakeman::Rails3RoutesProcessor < Brakeman::BaseProcessor
152
153
  end
153
154
 
154
155
  def process_verb exp
155
- args = exp[3][1..-1]
156
-
157
- if symbol? args[0] and not hash? args[1]
158
- add_route args[0]
159
- elsif hash? args[1]
160
- hash_iterate args[1] do |k, v|
161
- if symbol? k and k[1] == :to
156
+ args = exp.args
157
+ first_arg = args.first
158
+
159
+ if symbol? first_arg and not hash? args.second
160
+ add_route first_arg
161
+ elsif hash? args.second
162
+ hash_iterate args.second do |k, v|
163
+ if symbol? k and k.value == :to
162
164
  if string? v
163
- add_route_from_string v[1]
165
+ add_route_from_string v
164
166
  elsif in_controller_block? and symbol? v
165
167
  add_route v
166
168
  end
167
169
  end
168
170
  end
169
- elsif string? args[0]
170
- route = args[0][1].split "/"
171
+ elsif string? first_arg
172
+ route = first_arg.value.split "/"
171
173
  if route.length != 2
172
174
  add_route route[0]
173
175
  else
174
176
  add_route route[1], route[0]
175
177
  end
176
- elsif in_controller_block? and symbol? args[0]
177
- add_route args[0]
178
- else hash? args[0]
179
- hash_iterate args[0] do |k, v|
178
+ elsif in_controller_block? and symbol? first_arg
179
+ add_route first_arg
180
+ else hash? first_arg
181
+ hash_iterate first_arg do |k, v|
180
182
  if string? k
181
183
  if string? v
182
184
  add_route_from_string v
@@ -192,13 +194,13 @@ class Brakeman::Rails3RoutesProcessor < Brakeman::BaseProcessor
192
194
  end
193
195
 
194
196
  def process_resources exp
195
- if exp[3] and exp[3][2] and exp[3][2][0] == :hash
196
- self.current_controller = exp[3][1][1]
197
+ if exp.args and exp.args.second and exp.args.second.node_type == :hash
198
+ self.current_controller = exp.first_arg.value
197
199
  #handle hash
198
200
  add_resources_routes
199
- elsif exp[3][1..-1].all? { |s| symbol? s }
200
- exp[3][1..-1].each do |s|
201
- self.current_controller = s[1]
201
+ elsif exp.args.all? { |s| symbol? s }
202
+ exp.args.each do |s|
203
+ self.current_controller = s.value
202
204
  add_resources_routes
203
205
  end
204
206
  end
@@ -209,9 +211,9 @@ class Brakeman::Rails3RoutesProcessor < Brakeman::BaseProcessor
209
211
 
210
212
  def process_resource exp
211
213
  #Does resource even take more than one controller name?
212
- exp[3][1..-1].each do |s|
214
+ exp.args.each do |s|
213
215
  if symbol? s
214
- self.current_controller = pluralize(s[1].to_s)
216
+ self.current_controller = pluralize(s.value.to_s)
215
217
  add_resource_routes
216
218
  else
217
219
  #handle something else, like options
@@ -225,8 +227,8 @@ class Brakeman::Rails3RoutesProcessor < Brakeman::BaseProcessor
225
227
 
226
228
  def process_resources_block exp
227
229
  in_controller_block do
228
- process_resources exp[1]
229
- process exp[3]
230
+ process_resources exp.block_call
231
+ process exp.block
230
232
  end
231
233
 
232
234
  @current_controller = nil
@@ -235,8 +237,8 @@ class Brakeman::Rails3RoutesProcessor < Brakeman::BaseProcessor
235
237
 
236
238
  def process_resource_block exp
237
239
  in_controller_block do
238
- process_resource exp[1]
239
- process exp[3]
240
+ process_resource exp.block_call
241
+ process exp.block
240
242
  end
241
243
 
242
244
  @current_controller = nil
@@ -245,7 +247,7 @@ class Brakeman::Rails3RoutesProcessor < Brakeman::BaseProcessor
245
247
 
246
248
  def process_scope_block exp
247
249
  #How to deal with options?
248
- process exp[3]
250
+ process exp.block
249
251
  exp
250
252
  end
251
253
 
@@ -3,11 +3,11 @@ require 'digest/sha1'
3
3
  #Processes a call to render() in a controller or template
4
4
  module Brakeman::RenderHelper
5
5
 
6
- #Process s(:render, TYPE, OPTIONS)
6
+ #Process s(:render, TYPE, OPTION?, OPTIONS)
7
7
  def process_render exp
8
8
  process_default exp
9
9
  @rendered = true
10
- case exp[1]
10
+ case exp.render_type
11
11
  when :action, :template
12
12
  process_action exp[2][1], exp[3]
13
13
  when :default
@@ -40,7 +40,7 @@ module Brakeman::RenderHelper
40
40
  return
41
41
  end
42
42
 
43
- names = name[1].to_s.split("/")
43
+ names = name.value.to_s.split("/")
44
44
  names[-1] = "_" + names[-1]
45
45
  process_template template_name(names.join("/")), args
46
46
  end
@@ -92,7 +92,7 @@ module Brakeman::RenderHelper
92
92
 
93
93
  if hash? options[:locals]
94
94
  hash_iterate options[:locals] do |key, value|
95
- template_env[Sexp.new(:call, nil, key[1], Sexp.new(:arglist))] = value
95
+ template_env[Sexp.new(:call, nil, key.value, Sexp.new(:arglist))] = value
96
96
  end
97
97
  end
98
98
 
@@ -105,7 +105,7 @@ module Brakeman::RenderHelper
105
105
  #Unless the :as => :variable_name option is used
106
106
  if options[:as]
107
107
  if string? options[:as] or symbol? options[:as]
108
- variable = options[:as][1].to_sym
108
+ variable = options[:as].value.to_sym
109
109
  end
110
110
  end
111
111
 
@@ -148,7 +148,7 @@ module Brakeman::RenderHelper
148
148
 
149
149
  hash_iterate args do |key, value|
150
150
  if symbol? key
151
- options[key[1]] = value
151
+ options[key.value] = value
152
152
  end
153
153
  end
154
154
 
@@ -26,7 +26,7 @@ module Brakeman::RouteHelper
26
26
  #If no controller is specified, uses current controller value.
27
27
  def add_route route, controller = nil
28
28
  if node_type? route, :str, :lit
29
- route = route[1]
29
+ route = route.value
30
30
  end
31
31
 
32
32
  route = route.to_sym
@@ -16,7 +16,7 @@ class Brakeman::LibraryProcessor < Brakeman::BaseProcessor
16
16
  end
17
17
 
18
18
  def process_class exp
19
- name = class_name(exp[1])
19
+ name = class_name(exp.class_name)
20
20
 
21
21
  if @current_class
22
22
  outer_class = @current_class
@@ -31,7 +31,7 @@ class Brakeman::LibraryProcessor < Brakeman::BaseProcessor
31
31
  @current_class = @tracker.libs[name]
32
32
  else
33
33
  begin
34
- parent = class_name exp[2]
34
+ parent = class_name exp.parent_name
35
35
  rescue StandardError => e
36
36
  Brakeman.debug e
37
37
  parent = nil
@@ -49,7 +49,7 @@ class Brakeman::LibraryProcessor < Brakeman::BaseProcessor
49
49
  @tracker.libs[name] = @current_class
50
50
  end
51
51
 
52
- exp[3] = process exp[3]
52
+ exp.body = process exp.body
53
53
 
54
54
  if outer_class
55
55
  @current_class = outer_class
@@ -61,7 +61,7 @@ class Brakeman::LibraryProcessor < Brakeman::BaseProcessor
61
61
  end
62
62
 
63
63
  def process_module exp
64
- name = class_name(exp[1])
64
+ name = class_name(exp.module_name)
65
65
 
66
66
  if @current_module
67
67
  outer_class = @current_module
@@ -86,7 +86,7 @@ class Brakeman::LibraryProcessor < Brakeman::BaseProcessor
86
86
  @tracker.libs[name] = @current_module
87
87
  end
88
88
 
89
- exp[2] = process exp[2]
89
+ exp.body = process exp.body
90
90
 
91
91
  if outer_class
92
92
  @current_module = outer_class
@@ -99,12 +99,12 @@ class Brakeman::LibraryProcessor < Brakeman::BaseProcessor
99
99
 
100
100
  def process_defn exp
101
101
  exp = @alias_processor.process exp
102
- exp[0] = :methdef
102
+ exp.node_type = :methdef
103
103
 
104
104
  if @current_class
105
- @current_class[:public][exp[1]] = exp
105
+ @current_class[:public][exp.method_name] = exp
106
106
  elsif @current_module
107
- @current_module[:public][exp[1]] = exp
107
+ @current_module[:public][exp.method_name] = exp
108
108
  end
109
109
 
110
110
  exp
@@ -112,12 +112,12 @@ class Brakeman::LibraryProcessor < Brakeman::BaseProcessor
112
112
 
113
113
  def process_defs exp
114
114
  exp = @alias_processor.process exp
115
- exp[0] = :selfdef
115
+ exp.node_type = :selfdef
116
116
 
117
117
  if @current_class
118
- @current_class[:public][exp[2]] = exp
118
+ @current_class[:public][exp.method_name] = exp
119
119
  elsif @current_module
120
- @current_module[:public][exp[3]] = exp
120
+ @current_module[:public][exp.method_name] = exp
121
121
  end
122
122
 
123
123
  exp
@@ -18,18 +18,20 @@ class Brakeman::ModelProcessor < Brakeman::BaseProcessor
18
18
 
19
19
  #s(:class, NAME, PARENT, s(:scope ...))
20
20
  def process_class exp
21
+ name = class_name exp.class_name
22
+
21
23
  if @model
22
- Brakeman.debug "[Notice] Skipping inner class: #{class_name exp[1]}"
24
+ Brakeman.debug "[Notice] Skipping inner class: #{name}"
23
25
  ignore
24
26
  else
25
27
  begin
26
- parent = class_name exp[2]
28
+ parent = class_name exp.parent_name
27
29
  rescue StandardError => e
28
30
  Brakeman.debug e
29
31
  parent = nil
30
32
  end
31
33
 
32
- @model = { :name => class_name(exp[1]),
34
+ @model = { :name => name,
33
35
  :parent => parent,
34
36
  :includes => [],
35
37
  :public => {},
@@ -38,7 +40,7 @@ class Brakeman::ModelProcessor < Brakeman::BaseProcessor
38
40
  :options => {},
39
41
  :file => @file_name }
40
42
  @tracker.models[@model[:name]] = @model
41
- res = process exp[3]
43
+ res = process exp.body
42
44
  @model = nil
43
45
  res
44
46
  end
@@ -48,18 +50,18 @@ class Brakeman::ModelProcessor < Brakeman::BaseProcessor
48
50
  #such as include, attr_accessible, private, etc.
49
51
  def process_call exp
50
52
  return exp unless @model
51
- target = exp[1]
53
+ target = exp.target
52
54
  if sexp? target
53
55
  target = process target
54
56
  end
55
57
 
56
- method = exp[2]
57
- args = exp[3]
58
+ method = exp.method
59
+ args = exp.args
58
60
 
59
61
  #Methods called inside class definition
60
62
  #like attr_* and other settings
61
63
  if @current_method.nil? and target.nil?
62
- if args.length == 1 #actually, empty
64
+ if args.empty?
63
65
  case method
64
66
  when :private, :protected, :public
65
67
  @visibility = method
@@ -71,10 +73,10 @@ class Brakeman::ModelProcessor < Brakeman::BaseProcessor
71
73
  else
72
74
  case method
73
75
  when :include
74
- @model[:includes] << class_name(args[1]) if @model
76
+ @model[:includes] << class_name(args.first) if @model
75
77
  when :attr_accessible
76
78
  @model[:attr_accessible] ||= []
77
- args = args[1..-1].map do |e|
79
+ args = args.map do |e|
78
80
  e[1]
79
81
  end
80
82
 
@@ -82,13 +84,13 @@ class Brakeman::ModelProcessor < Brakeman::BaseProcessor
82
84
  else
83
85
  if @model
84
86
  @model[:options][method] ||= []
85
- @model[:options][method] << args
87
+ @model[:options][method] << exp.arglist
86
88
  end
87
89
  end
88
90
  end
89
91
  ignore
90
92
  else
91
- call = Sexp.new :call, target, method, process(args)
93
+ call = Sexp.new :call, target, method, process(exp.arglist)
92
94
  call.line(exp.line)
93
95
  call
94
96
  end
@@ -97,10 +99,10 @@ class Brakeman::ModelProcessor < Brakeman::BaseProcessor
97
99
  #Add method definition to tracker
98
100
  def process_defn exp
99
101
  return exp unless @model
100
- name = exp[1]
102
+ name = exp.method_name
101
103
 
102
104
  @current_method = name
103
- res = Sexp.new :methdef, name, process(exp[2]), process(exp[3][1])
105
+ res = Sexp.new :methdef, name, exp[2], process(exp.body.value)
104
106
  res.line(exp.line)
105
107
  @current_method = nil
106
108
  if @model
@@ -113,7 +115,7 @@ class Brakeman::ModelProcessor < Brakeman::BaseProcessor
113
115
  #Add method definition to tracker
114
116
  def process_defs exp
115
117
  return exp unless @model
116
- name = exp[2]
118
+ name = exp.method_name
117
119
 
118
120
  if exp[1].node_type == :self
119
121
  target = @model[:name]
@@ -122,7 +124,7 @@ class Brakeman::ModelProcessor < Brakeman::BaseProcessor
122
124
  end
123
125
 
124
126
  @current_method = name
125
- res = Sexp.new :selfdef, target, name, process(exp[3]), process(exp[4][1])
127
+ res = Sexp.new :selfdef, target, name, exp[3], process(exp.body.value)
126
128
  res.line(exp.line)
127
129
  @current_method = nil
128
130
  if @model