brakeman-lib 4.5.0 → 4.7.1
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.
- checksums.yaml +4 -4
- data/CHANGES.md +164 -108
- data/README.md +6 -7
- data/lib/brakeman.rb +7 -0
- data/lib/brakeman/app_tree.rb +34 -22
- data/lib/brakeman/call_index.rb +54 -15
- data/lib/brakeman/checks.rb +7 -7
- data/lib/brakeman/checks/base_check.rb +59 -56
- data/lib/brakeman/checks/check_cookie_serialization.rb +22 -0
- data/lib/brakeman/checks/check_cross_site_scripting.rb +9 -4
- data/lib/brakeman/checks/check_default_routes.rb +5 -0
- data/lib/brakeman/checks/check_deserialize.rb +49 -0
- data/lib/brakeman/checks/check_dynamic_finders.rb +1 -1
- data/lib/brakeman/checks/check_execute.rb +26 -1
- data/lib/brakeman/checks/check_file_access.rb +7 -1
- data/lib/brakeman/checks/check_force_ssl.rb +27 -0
- data/lib/brakeman/checks/check_header_dos.rb +2 -2
- data/lib/brakeman/checks/check_i18n_xss.rb +2 -2
- data/lib/brakeman/checks/check_jruby_xml.rb +2 -2
- data/lib/brakeman/checks/check_json_parsing.rb +7 -2
- data/lib/brakeman/checks/check_link_to_href.rb +6 -1
- data/lib/brakeman/checks/check_mail_to.rb +1 -1
- data/lib/brakeman/checks/check_mime_type_dos.rb +2 -2
- data/lib/brakeman/checks/check_model_attr_accessible.rb +1 -1
- data/lib/brakeman/checks/check_model_attributes.rb +12 -50
- data/lib/brakeman/checks/check_model_serialize.rb +1 -1
- data/lib/brakeman/checks/check_nested_attributes_bypass.rb +4 -4
- data/lib/brakeman/checks/check_reverse_tabnabbing.rb +58 -0
- data/lib/brakeman/checks/check_sanitize_methods.rb +2 -2
- data/lib/brakeman/checks/check_secrets.rb +1 -1
- data/lib/brakeman/checks/check_session_settings.rb +15 -12
- data/lib/brakeman/checks/check_simple_format.rb +5 -0
- data/lib/brakeman/checks/check_skip_before_filter.rb +1 -1
- data/lib/brakeman/checks/check_sql.rb +15 -17
- data/lib/brakeman/checks/check_validation_regex.rb +1 -1
- data/lib/brakeman/checks/check_xml_dos.rb +2 -2
- data/lib/brakeman/checks/check_yaml_parsing.rb +10 -18
- data/lib/brakeman/differ.rb +16 -28
- data/lib/brakeman/file_parser.rb +10 -16
- data/lib/brakeman/file_path.rb +85 -0
- data/lib/brakeman/options.rb +7 -0
- data/lib/brakeman/parsers/haml_embedded.rb +1 -1
- data/lib/brakeman/parsers/template_parser.rb +6 -4
- data/lib/brakeman/processor.rb +4 -5
- data/lib/brakeman/processors/alias_processor.rb +27 -7
- data/lib/brakeman/processors/base_processor.rb +10 -7
- data/lib/brakeman/processors/controller_alias_processor.rb +10 -7
- data/lib/brakeman/processors/controller_processor.rb +9 -13
- data/lib/brakeman/processors/gem_processor.rb +10 -2
- data/lib/brakeman/processors/haml_template_processor.rb +92 -123
- data/lib/brakeman/processors/lib/call_conversion_helper.rb +5 -4
- data/lib/brakeman/processors/lib/find_all_calls.rb +27 -4
- data/lib/brakeman/processors/lib/find_call.rb +3 -64
- data/lib/brakeman/processors/lib/module_helper.rb +8 -8
- data/lib/brakeman/processors/lib/processor_helper.rb +3 -3
- data/lib/brakeman/processors/lib/rails2_config_processor.rb +4 -4
- data/lib/brakeman/processors/lib/rails2_route_processor.rb +2 -2
- data/lib/brakeman/processors/lib/rails3_config_processor.rb +3 -3
- data/lib/brakeman/processors/lib/rails3_route_processor.rb +2 -2
- data/lib/brakeman/processors/lib/render_helper.rb +2 -2
- data/lib/brakeman/processors/lib/render_path.rb +18 -1
- data/lib/brakeman/processors/library_processor.rb +5 -5
- data/lib/brakeman/processors/model_processor.rb +4 -5
- data/lib/brakeman/processors/output_processor.rb +5 -0
- data/lib/brakeman/processors/template_alias_processor.rb +32 -5
- data/lib/brakeman/processors/template_processor.rb +14 -10
- data/lib/brakeman/report.rb +3 -3
- data/lib/brakeman/report/ignore/config.rb +2 -3
- data/lib/brakeman/report/ignore/interactive.rb +2 -2
- data/lib/brakeman/report/pager.rb +1 -0
- data/lib/brakeman/report/report_base.rb +51 -6
- data/lib/brakeman/report/report_codeclimate.rb +3 -3
- data/lib/brakeman/report/report_hash.rb +1 -1
- data/lib/brakeman/report/report_html.rb +2 -2
- data/lib/brakeman/report/report_json.rb +1 -24
- data/lib/brakeman/report/report_table.rb +20 -4
- data/lib/brakeman/report/report_tabs.rb +1 -1
- data/lib/brakeman/report/report_text.rb +6 -7
- data/lib/brakeman/rescanner.rb +13 -12
- data/lib/brakeman/scanner.rb +19 -14
- data/lib/brakeman/tracker.rb +30 -6
- data/lib/brakeman/tracker/collection.rb +4 -3
- data/lib/brakeman/tracker/config.rb +44 -73
- data/lib/brakeman/tracker/constants.rb +2 -1
- data/lib/brakeman/util.rb +1 -147
- data/lib/brakeman/version.rb +1 -1
- data/lib/brakeman/warning.rb +27 -13
- data/lib/brakeman/warning_codes.rb +4 -0
- data/lib/ruby_parser/bm_sexp.rb +7 -2
- data/lib/ruby_parser/bm_sexp_processor.rb +1 -0
- metadata +27 -22
@@ -8,20 +8,16 @@ class Brakeman::ControllerProcessor < Brakeman::BaseProcessor
|
|
8
8
|
|
9
9
|
FORMAT_HTML = Sexp.new(:call, Sexp.new(:lvar, :format), :html)
|
10
10
|
|
11
|
-
def initialize
|
11
|
+
def initialize tracker, current_file = nil
|
12
12
|
super(tracker)
|
13
|
-
@app_tree = app_tree
|
14
|
-
@current_class = nil
|
15
|
-
@current_method = nil
|
16
|
-
@current_module = nil
|
17
13
|
@visibility = :public
|
18
|
-
@
|
14
|
+
@current_file = current_file
|
19
15
|
@concerns = Set.new
|
20
16
|
end
|
21
17
|
|
22
18
|
#Use this method to process a Controller
|
23
|
-
def process_controller src,
|
24
|
-
@
|
19
|
+
def process_controller src, current_file = @current_file
|
20
|
+
@current_file = current_file
|
25
21
|
process src
|
26
22
|
end
|
27
23
|
|
@@ -35,7 +31,7 @@ class Brakeman::ControllerProcessor < Brakeman::BaseProcessor
|
|
35
31
|
#a real controller, so we can't take this shortcut.
|
36
32
|
if @current_class and @current_class.name.to_s.end_with? "Controller"
|
37
33
|
Brakeman.debug "[Notice] Treating inner class as library: #{name}"
|
38
|
-
Brakeman::LibraryProcessor.new(@tracker).process_library exp, @
|
34
|
+
Brakeman::LibraryProcessor.new(@tracker).process_library exp, @current_file
|
39
35
|
return exp
|
40
36
|
end
|
41
37
|
|
@@ -196,8 +192,8 @@ class Brakeman::ControllerProcessor < Brakeman::BaseProcessor
|
|
196
192
|
|
197
193
|
filter_name = ("fake_filter" + rand.to_s[/\d+$/]).to_sym
|
198
194
|
args = exp.block_call.arglist
|
199
|
-
args.insert(1, Sexp.new(:lit, filter_name))
|
200
|
-
before_filter_call = make_call(nil, :before_filter, args)
|
195
|
+
args.insert(1, Sexp.new(:lit, filter_name).line(exp.line))
|
196
|
+
before_filter_call = make_call(nil, :before_filter, args).line(exp.line)
|
201
197
|
|
202
198
|
if exp.block_args.length > 1
|
203
199
|
block_variable = exp.block_args[1]
|
@@ -214,9 +210,9 @@ class Brakeman::ControllerProcessor < Brakeman::BaseProcessor
|
|
214
210
|
#Build Sexp for filter method
|
215
211
|
body = Sexp.new(:lasgn,
|
216
212
|
block_variable,
|
217
|
-
Sexp.new(:call, Sexp.new(:const, @current_class.name), :new))
|
213
|
+
Sexp.new(:call, Sexp.new(:const, @current_class.name).line(exp.line), :new).line(exp.line)).line(exp.line)
|
218
214
|
|
219
|
-
filter_method = Sexp.new(:defn, filter_name, Sexp.new(:args), body).concat(block_inner).line(exp.line)
|
215
|
+
filter_method = Sexp.new(:defn, filter_name, Sexp.new(:args).line(exp.line), body).concat(block_inner).line(exp.line)
|
220
216
|
|
221
217
|
vis = @visibility
|
222
218
|
@visibility = :private
|
@@ -29,6 +29,14 @@ class Brakeman::GemProcessor < Brakeman::BasicProcessor
|
|
29
29
|
@tracker.config.set_rails_version
|
30
30
|
end
|
31
31
|
|
32
|
+
# Known issue: Brakeman does not yet support `gem` calls with multiple
|
33
|
+
# "version requirements". Consider the following example from the ruby docs:
|
34
|
+
#
|
35
|
+
# gem 'rake', '>= 1.1.a', '< 2'
|
36
|
+
#
|
37
|
+
# We are assuming that `second_arg` (eg. '>= 1.1.a') is the only requirement.
|
38
|
+
# Perhaps we should instantiate an array of `::Gem::Requirement`s or even a
|
39
|
+
# `::Gem::Dependency` and pass that to `Tracker::Config#add_gem`?
|
32
40
|
def process_call exp
|
33
41
|
if exp.target == nil
|
34
42
|
if exp.method == :gem
|
@@ -51,8 +59,8 @@ class Brakeman::GemProcessor < Brakeman::BasicProcessor
|
|
51
59
|
end
|
52
60
|
end
|
53
61
|
elsif @inside_gemspec and exp.method == :add_dependency
|
54
|
-
if string? exp.first_arg and string? exp.
|
55
|
-
@tracker.config.add_gem exp.first_arg.value, exp.
|
62
|
+
if string? exp.first_arg and string? exp.second_arg
|
63
|
+
@tracker.config.add_gem exp.first_arg.value, exp.second_arg.value, @gemspec, exp.line
|
56
64
|
end
|
57
65
|
end
|
58
66
|
|
@@ -2,137 +2,60 @@ require 'brakeman/processors/template_processor'
|
|
2
2
|
|
3
3
|
#Processes HAML templates.
|
4
4
|
class Brakeman::HamlTemplateProcessor < Brakeman::TemplateProcessor
|
5
|
-
|
5
|
+
HAMLOUT = s(:call, nil, :_hamlout)
|
6
|
+
HAML_BUFFER = s(:call, HAMLOUT, :buffer)
|
6
7
|
HAML_HELPERS = s(:colon2, s(:const, :Haml), :Helpers)
|
8
|
+
HAML_HELPERS2 = s(:colon2, s(:colon3, :Haml), :Helpers)
|
7
9
|
JAVASCRIPT_FILTER = s(:colon2, s(:colon2, s(:const, :Haml), :Filters), :Javascript)
|
8
10
|
COFFEE_FILTER = s(:colon2, s(:colon2, s(:const, :Haml), :Filters), :Coffee)
|
9
11
|
|
12
|
+
def initialize *args
|
13
|
+
super
|
14
|
+
@javascript = false
|
15
|
+
end
|
16
|
+
|
10
17
|
#Processes call, looking for template output
|
11
18
|
def process_call exp
|
12
|
-
|
13
|
-
|
14
|
-
|
19
|
+
exp = process_default exp
|
20
|
+
|
21
|
+
if buffer_append? exp
|
22
|
+
output = normalize_output(exp.first_arg)
|
23
|
+
res = get_pushed_value(output)
|
15
24
|
end
|
16
25
|
|
17
|
-
|
18
|
-
|
19
|
-
if (call? target and target.method == :_hamlout)
|
20
|
-
res = case method
|
21
|
-
when :adjust_tabs, :rstrip!, :attributes #Check attributes, maybe?
|
22
|
-
ignore
|
23
|
-
when :options, :buffer
|
24
|
-
exp
|
25
|
-
when :open_tag
|
26
|
-
process_call_args exp
|
27
|
-
else
|
28
|
-
arg = exp.first_arg
|
29
|
-
|
30
|
-
if arg
|
31
|
-
@inside_concat = true
|
32
|
-
exp.first_arg = process(arg)
|
33
|
-
out = normalize_output(exp.first_arg)
|
34
|
-
@inside_concat = false
|
35
|
-
else
|
36
|
-
raise "Empty _hamlout.#{method}()?"
|
37
|
-
end
|
38
|
-
|
39
|
-
if string? out
|
40
|
-
ignore
|
41
|
-
else
|
42
|
-
r = case method.to_s
|
43
|
-
when "push_text"
|
44
|
-
build_output_from_push_text(out)
|
45
|
-
when HAML_FORMAT_METHOD
|
46
|
-
if $4 == "true"
|
47
|
-
if string_interp? out
|
48
|
-
build_output_from_push_text(out, :escaped_output)
|
49
|
-
else
|
50
|
-
Sexp.new :format_escaped, out
|
51
|
-
end
|
52
|
-
else
|
53
|
-
if string_interp? out
|
54
|
-
build_output_from_push_text(out)
|
55
|
-
else
|
56
|
-
Sexp.new :format, out
|
57
|
-
end
|
58
|
-
end
|
59
|
-
|
60
|
-
else
|
61
|
-
raise "Unrecognized action on _hamlout: #{method}"
|
62
|
-
end
|
63
|
-
|
64
|
-
@javascript = false
|
65
|
-
r
|
66
|
-
end
|
67
|
-
end
|
68
|
-
|
69
|
-
res.line(exp.line)
|
70
|
-
res
|
71
|
-
|
72
|
-
#_hamlout.buffer <<
|
73
|
-
#This seems to be used rarely, but directly appends args to output buffer.
|
74
|
-
#Has something to do with values of blocks?
|
75
|
-
elsif sexp? target and method == :<< and is_buffer_target? target
|
76
|
-
@inside_concat = true
|
77
|
-
exp.first_arg = process(exp.first_arg)
|
78
|
-
out = normalize_output(exp.first_arg)
|
79
|
-
@inside_concat = false
|
80
|
-
|
81
|
-
if out.node_type == :str #ignore plain strings
|
82
|
-
ignore
|
83
|
-
else
|
84
|
-
add_output out
|
85
|
-
end
|
86
|
-
elsif target == nil and method == :render
|
87
|
-
#Process call to render()
|
88
|
-
exp.arglist = process exp.arglist
|
89
|
-
make_render_in_view exp
|
90
|
-
elsif target == nil and method == :find_and_preserve and exp.first_arg
|
91
|
-
process exp.first_arg
|
92
|
-
elsif method == :render_with_options
|
93
|
-
if target == JAVASCRIPT_FILTER or target == COFFEE_FILTER
|
94
|
-
@javascript = true
|
95
|
-
end
|
26
|
+
res or exp
|
27
|
+
end
|
96
28
|
|
97
|
-
|
98
|
-
|
99
|
-
|
100
|
-
exp.
|
101
|
-
exp
|
102
|
-
|
29
|
+
# _haml_out.buffer << ...
|
30
|
+
def buffer_append? exp
|
31
|
+
call? exp and
|
32
|
+
exp.target == HAML_BUFFER and
|
33
|
+
exp.method == :<<
|
34
|
+
end
|
35
|
+
|
36
|
+
PRESERVE_METHODS = [:find_and_preserve, :preserve]
|
37
|
+
|
38
|
+
def find_and_preserve? exp
|
39
|
+
call? exp and
|
40
|
+
PRESERVE_METHODS.include?(exp.method) and
|
41
|
+
exp.first_arg
|
103
42
|
end
|
104
43
|
|
105
44
|
#If inside an output stream, only return the final expression
|
106
45
|
def process_block exp
|
107
46
|
exp = exp.dup
|
108
47
|
exp.shift
|
109
|
-
|
110
|
-
|
111
|
-
|
112
|
-
|
113
|
-
|
114
|
-
|
115
|
-
|
116
|
-
else
|
117
|
-
exp.map! do |e|
|
118
|
-
res = process e
|
119
|
-
if res.empty?
|
120
|
-
nil
|
121
|
-
else
|
122
|
-
res
|
123
|
-
end
|
48
|
+
|
49
|
+
exp.map! do |e|
|
50
|
+
res = process e
|
51
|
+
if res.empty?
|
52
|
+
nil
|
53
|
+
else
|
54
|
+
res
|
124
55
|
end
|
125
|
-
Sexp.new(:rlist).concat(exp).compact
|
126
56
|
end
|
127
|
-
end
|
128
57
|
|
129
|
-
|
130
|
-
#TODO: Test this
|
131
|
-
def is_buffer_target? exp
|
132
|
-
exp.node_type == :call and
|
133
|
-
node_type? exp.target, :lvar and
|
134
|
-
exp.target.value == :_hamlout and
|
135
|
-
exp.method == :buffer
|
58
|
+
Sexp.new(:rlist).concat(exp).compact
|
136
59
|
end
|
137
60
|
|
138
61
|
#HAML likes to put interpolated values into _hamlout.push_text
|
@@ -153,7 +76,6 @@ class Brakeman::HamlTemplateProcessor < Brakeman::TemplateProcessor
|
|
153
76
|
end
|
154
77
|
end
|
155
78
|
|
156
|
-
#Gets outputs from values interpolated into _hamlout.push_text
|
157
79
|
def get_pushed_value exp, default = :output
|
158
80
|
return exp unless sexp? exp
|
159
81
|
|
@@ -168,24 +90,71 @@ class Brakeman::HamlTemplateProcessor < Brakeman::TemplateProcessor
|
|
168
90
|
exp
|
169
91
|
when :str, :ignore, :output, :escaped_output
|
170
92
|
exp
|
171
|
-
when :block, :rlist
|
172
|
-
exp.map! { |e| get_pushed_value
|
93
|
+
when :block, :rlist
|
94
|
+
exp.map! { |e| get_pushed_value(e, default) }
|
95
|
+
when :dstr
|
96
|
+
build_output_from_push_text(exp, default)
|
173
97
|
when :if
|
174
|
-
clauses = [get_pushed_value(exp.then_clause), get_pushed_value(exp.else_clause)].compact
|
98
|
+
clauses = [get_pushed_value(exp.then_clause, default), get_pushed_value(exp.else_clause, default)].compact
|
175
99
|
|
176
100
|
if clauses.length > 1
|
177
|
-
s(:or, *clauses)
|
101
|
+
s(:or, *clauses).line(exp.line)
|
178
102
|
else
|
179
103
|
clauses.first
|
180
104
|
end
|
181
|
-
|
182
|
-
if
|
183
|
-
|
184
|
-
elsif
|
185
|
-
|
105
|
+
when :call
|
106
|
+
if exp.method == :to_s or exp.method == :strip
|
107
|
+
get_pushed_value(exp.target, default)
|
108
|
+
elsif haml_helpers? exp.target and exp.method == :html_escape
|
109
|
+
get_pushed_value(exp.first_arg, :escaped_output)
|
110
|
+
elsif @javascript and (exp.method == :j or exp.method == :escape_javascript) # TODO: Remove - this is not safe
|
111
|
+
get_pushed_value(exp.first_arg, :escaped_output)
|
112
|
+
elsif find_and_preserve? exp or fix_textareas? exp
|
113
|
+
get_pushed_value(exp.first_arg, default)
|
114
|
+
elsif raw? exp
|
115
|
+
get_pushed_value(exp.first_arg, :output)
|
116
|
+
elsif hamlout_attributes? exp
|
117
|
+
ignore # ignore _hamlout.attributes calls
|
118
|
+
elsif exp.target.nil? and exp.method == :render
|
119
|
+
#Process call to render()
|
120
|
+
exp.arglist = process exp.arglist
|
121
|
+
make_render_in_view exp
|
122
|
+
elsif exp.method == :render_with_options
|
123
|
+
if exp.target == JAVASCRIPT_FILTER or exp.target == COFFEE_FILTER
|
124
|
+
@javascript = true
|
125
|
+
end
|
126
|
+
|
127
|
+
get_pushed_value(exp.first_arg, default)
|
128
|
+
@javascript = false
|
186
129
|
else
|
187
130
|
add_output exp, default
|
188
131
|
end
|
132
|
+
else
|
133
|
+
add_output exp, default
|
189
134
|
end
|
190
135
|
end
|
136
|
+
|
137
|
+
def haml_helpers? exp
|
138
|
+
# Sometimes its Haml::Helpers and
|
139
|
+
# sometimes its ::Haml::Helpers
|
140
|
+
exp == HAML_HELPERS or
|
141
|
+
exp == HAML_HELPERS2
|
142
|
+
end
|
143
|
+
|
144
|
+
def hamlout_attributes? exp
|
145
|
+
call? exp and
|
146
|
+
exp.target == HAMLOUT and
|
147
|
+
exp.method == :attributes
|
148
|
+
end
|
149
|
+
|
150
|
+
def fix_textareas? exp
|
151
|
+
call? exp and
|
152
|
+
exp.target == HAMLOUT and
|
153
|
+
exp.method == :fix_textareas!
|
154
|
+
end
|
155
|
+
|
156
|
+
def raw? exp
|
157
|
+
call? exp and
|
158
|
+
exp.method == :raw
|
159
|
+
end
|
191
160
|
end
|
@@ -19,16 +19,17 @@ module Brakeman
|
|
19
19
|
end
|
20
20
|
end
|
21
21
|
|
22
|
+
STRING_LENGTH_LIMIT = 50
|
23
|
+
|
22
24
|
# Join two string literals into one.
|
23
25
|
def join_strings lhs, rhs, original_exp = nil
|
24
26
|
if string? lhs and string? rhs
|
25
|
-
|
26
|
-
result.value = lhs.value + rhs.value
|
27
|
-
|
28
|
-
if result.value.length > 50
|
27
|
+
if (lhs.value.length + rhs.value.length > STRING_LENGTH_LIMIT)
|
29
28
|
# Avoid gigantic strings
|
30
29
|
lhs
|
31
30
|
else
|
31
|
+
result = Sexp.new(:str).line(lhs.line)
|
32
|
+
result.value = lhs.value + rhs.value
|
32
33
|
result
|
33
34
|
end
|
34
35
|
elsif call? lhs and lhs.method == :+ and string? lhs.first_arg and string? rhs
|
@@ -5,9 +5,9 @@ class Brakeman::FindAllCalls < Brakeman::BasicProcessor
|
|
5
5
|
|
6
6
|
def initialize tracker
|
7
7
|
super
|
8
|
-
|
9
|
-
@current_method = nil
|
8
|
+
|
10
9
|
@in_target = false
|
10
|
+
@processing_class = false
|
11
11
|
@calls = []
|
12
12
|
@cache = {}
|
13
13
|
end
|
@@ -23,10 +23,33 @@ class Brakeman::FindAllCalls < Brakeman::BasicProcessor
|
|
23
23
|
process exp
|
24
24
|
end
|
25
25
|
|
26
|
+
#For whatever reason, originally the indexing of calls
|
27
|
+
#was performed on individual method bodies (see process_defn).
|
28
|
+
#This method explicitly indexes all calls everywhere given any
|
29
|
+
#source.
|
30
|
+
def process_all_source exp, opts
|
31
|
+
@processing_class = true
|
32
|
+
process_source exp, opts
|
33
|
+
ensure
|
34
|
+
@processing_class = false
|
35
|
+
end
|
36
|
+
|
26
37
|
#Process body of method
|
27
38
|
def process_defn exp
|
28
|
-
return exp unless @current_method
|
29
|
-
|
39
|
+
return exp unless @current_method or @processing_class
|
40
|
+
|
41
|
+
# 'Normal' processing assumes the method name was given
|
42
|
+
# as an option to `process_source` but for `process_all_source`
|
43
|
+
# we don't want to do that.
|
44
|
+
if @current_method.nil?
|
45
|
+
@current_method = exp.method_name
|
46
|
+
process_all exp.body
|
47
|
+
@current_method = nil
|
48
|
+
else
|
49
|
+
process_all exp.body
|
50
|
+
end
|
51
|
+
|
52
|
+
exp
|
30
53
|
end
|
31
54
|
|
32
55
|
alias process_defs process_defn
|
@@ -33,14 +33,13 @@ require 'brakeman/processors/lib/basic_processor'
|
|
33
33
|
# FindCall.new nil, /^g?sub!?$/
|
34
34
|
class Brakeman::FindCall < Brakeman::BasicProcessor
|
35
35
|
|
36
|
-
def initialize targets, methods, tracker
|
36
|
+
def initialize targets, methods, tracker
|
37
37
|
super tracker
|
38
38
|
@calls = []
|
39
39
|
@find_targets = targets
|
40
40
|
@find_methods = methods
|
41
41
|
@current_class = nil
|
42
42
|
@current_method = nil
|
43
|
-
@in_depth = in_depth
|
44
43
|
end
|
45
44
|
|
46
45
|
#Returns a list of results.
|
@@ -48,10 +47,6 @@ class Brakeman::FindCall < Brakeman::BasicProcessor
|
|
48
47
|
#A result looks like:
|
49
48
|
#
|
50
49
|
# s(:result, :ClassName, :method_name, s(:call, ...))
|
51
|
-
#
|
52
|
-
#or
|
53
|
-
#
|
54
|
-
# s(:result, :template_name, s(:call, ...))
|
55
50
|
def matches
|
56
51
|
@calls
|
57
52
|
end
|
@@ -60,10 +55,7 @@ class Brakeman::FindCall < Brakeman::BasicProcessor
|
|
60
55
|
#or the template. These names are used when reporting results.
|
61
56
|
#
|
62
57
|
#Use FindCall#matches to retrieve results.
|
63
|
-
def process_source exp
|
64
|
-
@current_class = klass
|
65
|
-
@current_method = method
|
66
|
-
@current_template = template
|
58
|
+
def process_source exp
|
67
59
|
process exp
|
68
60
|
end
|
69
61
|
|
@@ -74,11 +66,6 @@ class Brakeman::FindCall < Brakeman::BasicProcessor
|
|
74
66
|
|
75
67
|
alias :process_defs :process_defn
|
76
68
|
|
77
|
-
#Process body of block
|
78
|
-
def process_rlist exp
|
79
|
-
process_all exp
|
80
|
-
end
|
81
|
-
|
82
69
|
#Look for matching calls and add them to results
|
83
70
|
def process_call exp
|
84
71
|
target = get_target exp.target
|
@@ -87,25 +74,9 @@ class Brakeman::FindCall < Brakeman::BasicProcessor
|
|
87
74
|
process_call_args exp
|
88
75
|
|
89
76
|
if match(@find_targets, target) and match(@find_methods, method)
|
90
|
-
|
91
|
-
if @current_template
|
92
|
-
@calls << Sexp.new(:result, @current_template, exp).line(exp.line)
|
93
|
-
else
|
94
|
-
@calls << Sexp.new(:result, @current_module, @current_class, @current_method, exp).line(exp.line)
|
95
|
-
end
|
96
|
-
|
77
|
+
@calls << Sexp.new(:result, @current_module, @current_class, @current_method, exp).line(exp.line)
|
97
78
|
end
|
98
79
|
|
99
|
-
#Normally FindCall won't match a method invocation that is the target of
|
100
|
-
#another call, such as:
|
101
|
-
#
|
102
|
-
# User.find(:first, :conditions => "user = '#{params['user']}').name
|
103
|
-
#
|
104
|
-
#A search for User.find will not match this unless @in_depth is true.
|
105
|
-
if @in_depth and call? exp.target
|
106
|
-
process exp.target
|
107
|
-
end
|
108
|
-
|
109
80
|
exp
|
110
81
|
end
|
111
82
|
|
@@ -123,8 +94,6 @@ class Brakeman::FindCall < Brakeman::BasicProcessor
|
|
123
94
|
case exp.node_type
|
124
95
|
when :ivar, :lvar, :const, :lit
|
125
96
|
exp.value
|
126
|
-
when :true, :false
|
127
|
-
exp.node_type
|
128
97
|
when :colon2
|
129
98
|
class_name exp
|
130
99
|
else
|
@@ -141,43 +110,13 @@ class Brakeman::FindCall < Brakeman::BasicProcessor
|
|
141
110
|
when Symbol
|
142
111
|
if search_terms == item
|
143
112
|
true
|
144
|
-
elsif sexp? item
|
145
|
-
is_instance_of? item, search_terms
|
146
113
|
else
|
147
114
|
false
|
148
115
|
end
|
149
|
-
when Sexp
|
150
|
-
search_terms == item
|
151
116
|
when Enumerable
|
152
117
|
if search_terms.empty?
|
153
118
|
item == nil
|
154
|
-
else
|
155
|
-
search_terms.each do|term|
|
156
|
-
if match(term, item)
|
157
|
-
return true
|
158
|
-
end
|
159
|
-
end
|
160
|
-
false
|
161
119
|
end
|
162
|
-
when Regexp
|
163
|
-
search_terms.match item.to_s
|
164
|
-
when nil
|
165
|
-
true
|
166
|
-
else
|
167
|
-
raise "Cannot match #{search_terms} and #{item}"
|
168
|
-
end
|
169
|
-
end
|
170
|
-
|
171
|
-
#Checks if +item+ is an instance of +klass+ by looking for Klass.new
|
172
|
-
def is_instance_of? item, klass
|
173
|
-
if call? item
|
174
|
-
if sexp? item.target
|
175
|
-
item.method == :new and item.target.node_type == :const and item.target.value == klass
|
176
|
-
else
|
177
|
-
item.method == :new and item.target == klass
|
178
|
-
end
|
179
|
-
else
|
180
|
-
false
|
181
120
|
end
|
182
121
|
end
|
183
122
|
end
|