Module: Brakeman::Util

Overview

This is a mixin containing utility methods.

Constant Summary collapse

QUERY_PARAMETERS =
Sexp.new(:call, Sexp.new(:call, nil, :request), :query_parameters)
PATH_PARAMETERS =
Sexp.new(:call, Sexp.new(:call, nil, :request), :path_parameters)
REQUEST_PARAMETERS =
Sexp.new(:call, Sexp.new(:call, nil, :request), :request_parameters)
REQUEST_PARAMS =
Sexp.new(:call, Sexp.new(:call, nil, :request), :parameters)
REQUEST_ENV =
Sexp.new(:call, Sexp.new(:call, nil, :request), :env)
PARAMETERS =
Sexp.new(:call, nil, :params)
COOKIES =
Sexp.new(:call, nil, :cookies)
REQUEST_COOKIES =
s(:call, s(:call, nil, :request), :cookies)
SESSION =
Sexp.new(:call, nil, :session)
ALL_PARAMETERS =
Set[PARAMETERS, QUERY_PARAMETERS, PATH_PARAMETERS, REQUEST_PARAMETERS, REQUEST_PARAMS]
ALL_COOKIES =
Set[COOKIES, REQUEST_COOKIES]
SAFE_LITERAL =
s(:lit, :BRAKEMAN_SAFE_LITERAL)
PARAMS_SEXP =

These are never modified

Sexp.new(:params)
SESSION_SEXP =
Sexp.new(:session)
COOKIES_SEXP =
Sexp.new(:cookies)

Instance Method Summary collapse

Instance Method Details

#array?(exp) ⇒ Boolean

Check if exp represents an array: s(:array, […])

Returns:

  • (Boolean)


166
167
168
# File 'lib/brakeman/util.rb', line 166

def array? exp
  exp.is_a? Sexp and exp.node_type == :array
end

#block?(exp) ⇒ Boolean

Check if exp represents a block of code

Returns:

  • (Boolean)


224
225
226
227
# File 'lib/brakeman/util.rb', line 224

def block? exp
  exp.is_a? Sexp and (exp.node_type == :block or
                      exp.node_type == :rlist)
end

#call?(exp) ⇒ Boolean

Check if exp represents a method call: s(:call, …)

Returns:

  • (Boolean)


185
186
187
188
# File 'lib/brakeman/util.rb', line 185

def call? exp
  exp.is_a? Sexp and
    (exp.node_type == :call or exp.node_type == :safe_call)
end

#camelize(lower_case_and_underscored_word) ⇒ Object

Convert a string from “something_like_this” to “SomethingLikeThis”

Taken from ActiveSupport.



34
35
36
# File 'lib/brakeman/util.rb', line 34

def camelize lower_case_and_underscored_word
  lower_case_and_underscored_word.to_s.gsub(/\/(.?)/) { "::#{$1.upcase}" }.gsub(/(?:^|_)(.)/) { $1.upcase }
end

#class_name(exp) ⇒ Object

Returns a class name as a Symbol. If class name cannot be determined, returns exp.



56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
# File 'lib/brakeman/util.rb', line 56

def class_name exp
  case exp
  when Sexp
    case exp.node_type
    when :const
      exp.value
    when :lvar
      exp.value.to_sym
    when :colon2
      "#{class_name(exp.lhs)}::#{exp.rhs}".to_sym
    when :colon3
      "::#{exp.value}".to_sym
    when :self
      @current_class || @current_module || nil
    else
      exp
    end
  when Symbol
    exp
  when nil
    nil
  else
    exp
  end
end

#constant?(exp) ⇒ Boolean

Returns:

  • (Boolean)


273
274
275
# File 'lib/brakeman/util.rb', line 273

def constant? exp
  node_type? exp, :const, :colon2, :colon3
end

#contains_class?(exp) ⇒ Boolean

Returns true if the given exp contains a :class node.

Useful for checking if a module is just a module or if it is a namespace.

Returns:

  • (Boolean)


297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
# File 'lib/brakeman/util.rb', line 297

def contains_class? exp
  todo = [exp]

  until todo.empty?
    current = todo.shift

    if node_type? current, :class
      return true
    elsif sexp? current
      todo = current[1..-1].concat todo
    end
  end

  false
end

#cookies?(exp) ⇒ Boolean

Returns:

  • (Boolean)


246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
# File 'lib/brakeman/util.rb', line 246

def cookies? exp
  if exp.is_a? Sexp
    return true if exp.node_type == :cookies or ALL_COOKIES.include? exp

    if call? exp
      if cookies? exp[1]
        return true
      elsif exp[2] == :[]
        return cookies? exp[1]
      end
    end
  end

  false
end

#false?(exp) ⇒ Boolean

Check if exp represents a :false or :nil node

Returns:

  • (Boolean)


218
219
220
221
# File 'lib/brakeman/util.rb', line 218

def false? exp
  exp.is_a? Sexp and (exp.node_type == :false or
                      exp.node_type == :nil)
end

#hash?(exp) ⇒ Boolean

Check if exp represents a hash: s(:hash, …) This also includes pseudo hashes params, session, and cookies.

Returns:

  • (Boolean)


158
159
160
161
162
163
# File 'lib/brakeman/util.rb', line 158

def hash? exp
  exp.is_a? Sexp and (exp.node_type == :hash or
                      exp.node_type == :params or
                      exp.node_type == :session or
                      exp.node_type == :cookies)
end

#hash_access(hash, key) ⇒ Object

Get value from hash using key.

If key is a Symbol, it will be converted to a Sexp(:lit, key).



131
132
133
134
135
136
137
138
139
140
141
# File 'lib/brakeman/util.rb', line 131

def hash_access hash, key
  if key.is_a? Symbol
    key = Sexp.new(:lit, key)
  end

  if index = hash.find_index(key) and index > 0
    return hash[index + 1]
  end

  nil
end

#hash_insert(hash, key, value) ⇒ Object

Insert value into Hash Sexp



113
114
115
116
117
118
119
120
121
122
123
124
125
126
# File 'lib/brakeman/util.rb', line 113

def hash_insert hash, key, value
  index = 1
  hash_iterate hash.dup do |k,v|
    if k == key
      hash[index + 1] = value
      return hash
    end
    index += 2
  end

  hash << key << value

  hash
end

#hash_iterate(hash) ⇒ Object

Takes an Sexp like (:hash, (:lit, :key), (:str, “value”)) and yields the key and value pairs to the given block.

For example:

h = Sexp.new(:hash, (:lit, :name), (:str, “bob”), (:lit, :name), (:str, “jane”)) names = [] hash_iterate(h) do |key, value|

if symbol? key and key[1] == :name
  names << value[1]
end

end names #[“bob”]



96
97
98
99
100
101
102
# File 'lib/brakeman/util.rb', line 96

def hash_iterate hash
  hash = remove_kwsplat(hash)

  1.step(hash.length - 1, 2) do |i|
    yield hash[i], hash[i + 1]
  end
end

#integer?(exp) ⇒ Boolean

Check if exp represents an Integer: s(:lit, …)

Returns:

  • (Boolean)


196
197
198
# File 'lib/brakeman/util.rb', line 196

def integer? exp
  exp.is_a? Sexp and exp.node_type == :lit and exp[1].is_a? Integer
end

#kwsplat?(exp) ⇒ Boolean

Returns:

  • (Boolean)


277
278
279
280
281
282
# File 'lib/brakeman/util.rb', line 277

def kwsplat? exp
  exp.is_a? Sexp and
    exp.node_type == :hash and
    exp[1].is_a? Sexp and
    exp[1].node_type == :kwsplat
end

#make_call(target, method, *args) ⇒ Object



313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
# File 'lib/brakeman/util.rb', line 313

def make_call target, method, *args
  call = Sexp.new(:call, target, method)

  if args.empty? or args.first.empty?
    #nothing to do
  elsif node_type? args.first, :arglist
    call.concat args.first[1..-1]
  elsif args.first.node_type.is_a? Sexp #just a list of args
    call.concat args.first
  else
    call.concat args
  end

  call
end

#node_type?(exp, *types) ⇒ Boolean

Check if exp is a Sexp and the node type matches one of the given types.

Returns:

  • (Boolean)


290
291
292
# File 'lib/brakeman/util.rb', line 290

def node_type? exp, *types
  exp.is_a? Sexp and types.include? exp.node_type
end

#number?(exp) ⇒ Boolean

Check if exp represents a number: s(:lit, …)

Returns:

  • (Boolean)


201
202
203
# File 'lib/brakeman/util.rb', line 201

def number? exp
  exp.is_a? Sexp and exp.node_type == :lit and exp[1].is_a? Numeric
end

#params?(exp) ⇒ Boolean

Check if exp is a params hash

Returns:

  • (Boolean)


230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
# File 'lib/brakeman/util.rb', line 230

def params? exp
  if exp.is_a? Sexp
    return true if exp.node_type == :params or ALL_PARAMETERS.include? exp

    if call? exp
      if params? exp[1]
        return true
      elsif exp[2] == :[]
        return params? exp[1]
      end
    end
  end

  false
end

#pluralize(word) ⇒ Object

stupid simple, used to delegate to ActiveSupport



50
51
52
# File 'lib/brakeman/util.rb', line 50

def pluralize word
  word + "s"
end

#rails_versionObject



345
346
347
# File 'lib/brakeman/util.rb', line 345

def rails_version
  @tracker.config.rails_version
end

#regexp?(exp) ⇒ Boolean

Check if exp represents a Regexp: s(:lit, /…/)

Returns:

  • (Boolean)


191
192
193
# File 'lib/brakeman/util.rb', line 191

def regexp? exp
  exp.is_a? Sexp and exp.node_type == :lit and exp[1].is_a? Regexp
end

#remove_kwsplat(exp) ⇒ Object



104
105
106
107
108
109
110
# File 'lib/brakeman/util.rb', line 104

def remove_kwsplat exp
  if exp.any? { |e| node_type? e, :kwsplat }
    exp.reject { |e| node_type? e, :kwsplat }
  else
    exp
  end
end

#request_env?(exp) ⇒ Boolean

Returns:

  • (Boolean)


262
263
264
# File 'lib/brakeman/util.rb', line 262

def request_env? exp
  call? exp and (exp == REQUEST_ENV or exp[1] == REQUEST_ENV)
end

#request_value?(exp) ⇒ Boolean

Check if exp is params, cookies, or request_env

Returns:

  • (Boolean)


267
268
269
270
271
# File 'lib/brakeman/util.rb', line 267

def request_value? exp
  params? exp or
  cookies? exp or
  request_env? exp
end

#result?(exp) ⇒ Boolean

Check if exp represents a result: s(:result, …)

Returns:

  • (Boolean)


206
207
208
# File 'lib/brakeman/util.rb', line 206

def result? exp
  exp.is_a? Sexp and exp.node_type == :result
end

#safe_literal(line = nil) ⇒ Object



329
330
331
# File 'lib/brakeman/util.rb', line 329

def safe_literal line = nil
  s(:lit, :BRAKEMAN_SAFE_LITERAL).line(line || 0)
end

#safe_literal?(exp) ⇒ Boolean

Returns:

  • (Boolean)


333
334
335
# File 'lib/brakeman/util.rb', line 333

def safe_literal? exp
  exp == SAFE_LITERAL
end

#safe_literal_target?(exp) ⇒ Boolean

Returns:

  • (Boolean)


337
338
339
340
341
342
343
# File 'lib/brakeman/util.rb', line 337

def safe_literal_target? exp
  if call? exp
    safe_literal_target? exp.target
  else
    safe_literal? exp
  end
end

#set_env_defaultsObject

Adds params, session, and cookies to environment so they can be replaced by their respective Sexps.



150
151
152
153
154
# File 'lib/brakeman/util.rb', line 150

def set_env_defaults
  @env[PARAMETERS] = PARAMS_SEXP
  @env[SESSION] = SESSION_SEXP
  @env[COOKIES] = COOKIES_SEXP
end

#sexp?(exp) ⇒ Boolean

Check if exp is a Sexp.

Returns:

  • (Boolean)


285
286
287
# File 'lib/brakeman/util.rb', line 285

def sexp? exp
  exp.is_a? Sexp
end

#string?(exp) ⇒ Boolean

Check if exp represents a String: s(:str, “…”)

Returns:

  • (Boolean)


171
172
173
# File 'lib/brakeman/util.rb', line 171

def string? exp
  exp.is_a? Sexp and exp.node_type == :str
end

#string_interp?(exp) ⇒ Boolean

Returns:

  • (Boolean)


175
176
177
# File 'lib/brakeman/util.rb', line 175

def string_interp? exp
  exp.is_a? Sexp and exp.node_type == :dstr
end

#symbol?(exp) ⇒ Boolean

Check if exp represents a Symbol: s(:lit, :…)

Returns:

  • (Boolean)


180
181
182
# File 'lib/brakeman/util.rb', line 180

def symbol? exp
  exp.is_a? Sexp and exp.node_type == :lit and exp[1].is_a? Symbol
end

#template_path_to_name(path) ⇒ Object

Convert path/filename to view name

views/test/something.html.erb -> test/something



352
353
354
355
356
# File 'lib/brakeman/util.rb', line 352

def template_path_to_name path
  names = path.relative.split("/")
  names.last.gsub!(/(\.(html|js)\..*|\.(rhtml|haml|erb|slim))$/, '')
  names[(names.index("views") + 1)..-1].join("/").to_sym
end

#true?(exp) ⇒ Boolean

Check if exp represents a :true, :lit, or :string node

Returns:

  • (Boolean)


211
212
213
214
215
# File 'lib/brakeman/util.rb', line 211

def true? exp
  exp.is_a? Sexp and (exp.node_type == :true or
                      exp.node_type == :lit or
                      exp.node_type == :string)
end

#underscore(camel_cased_word) ⇒ Object

Convert a string from “Something::LikeThis” to “something/like_this”

Taken from ActiveSupport.



41
42
43
44
45
46
47
# File 'lib/brakeman/util.rb', line 41

def underscore camel_cased_word
  camel_cased_word.to_s.gsub(/::/, '/').
    gsub(/([A-Z]+)([A-Z][a-z])/,'\1_\2').
    gsub(/([a-z\d])([A-Z])/,'\1_\2').
    tr("-", "_").
    downcase
end