Module: Brakeman::CallConversionHelper

Included in:
AliasProcessor
Defined in:
lib/brakeman/processors/lib/call_conversion_helper.rb

Constant Summary collapse

STRING_LENGTH_LIMIT =
50

Instance Method Summary collapse

Instance Method Details

#all_literals?(exp, expected_type = :array) ⇒ Boolean

Returns:

  • (Boolean)

3
4
5
6
7
# File 'lib/brakeman/processors/lib/call_conversion_helper.rb', line 3

def all_literals? exp, expected_type = :array
  node_type? exp, expected_type and
    exp.length > 1 and
    exp.all? { |e| e.is_a? Symbol or node_type? e, :lit, :str }
end

#join_arrays(lhs, rhs, original_exp = nil) ⇒ Object

Join two array literals into one.


10
11
12
13
14
15
16
17
18
19
20
# File 'lib/brakeman/processors/lib/call_conversion_helper.rb', line 10

def join_arrays lhs, rhs, original_exp = nil
  if array? lhs and array? rhs
    result = Sexp.new(:array)
    result.line(lhs.line || rhs.line || 1)
    result.concat lhs[1..-1]
    result.concat rhs[1..-1]
    result
  else
    original_exp
  end
end

#join_strings(lhs, rhs, original_exp = nil) ⇒ Object

Join two string literals into one.


25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
# File 'lib/brakeman/processors/lib/call_conversion_helper.rb', line 25

def join_strings lhs, rhs, original_exp = nil
  if string? lhs and string? rhs
    if (lhs.value.length + rhs.value.length > STRING_LENGTH_LIMIT)
      # Avoid gigantic strings
      lhs
    else
      result = Sexp.new(:str).line(lhs.line)
      result.value = lhs.value + rhs.value
      result
    end
  elsif call? lhs and lhs.method == :+ and string? lhs.first_arg and string? rhs
    joined = join_strings lhs.first_arg, rhs
    lhs.first_arg = joined
    lhs
  elsif safe_literal? lhs or safe_literal? rhs
    safe_literal(lhs.line)
  else
    original_exp
  end
rescue Encoding::CompatibilityError => e
  # If the two strings are different encodings, we can't join them.
  Brakeman.debug e.inspect
  original_exp
end

#math_op(op, lhs, rhs, original_exp = nil) ⇒ Object


50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
# File 'lib/brakeman/processors/lib/call_conversion_helper.rb', line 50

def math_op op, lhs, rhs, original_exp = nil
  if number? lhs and number? rhs
    if op == :/ and rhs.value == 0 and not lhs.value.is_a? Float
      # Avoid division by zero
      return original_exp
    else
      value = lhs.value.send(op, rhs.value)
      Sexp.new(:lit, value).line(lhs.line)
    end
  elsif call? lhs and lhs.method == :+ and number? lhs.first_arg and number? rhs
    # (x + 1) + 2 -> (x + 3)
    lhs.first_arg = Sexp.new(:lit, lhs.first_arg.value + rhs.value).line(lhs.first_arg.line)
    lhs
  elsif safe_literal? lhs or safe_literal? rhs
    safe_literal(lhs.line)
  else
    original_exp
  end
end

#process_array_access(array, args, original_exp = nil) ⇒ Object

Process single integer access to an array.

Returns the value inside the array, if possible.


73
74
75
76
77
78
79
80
81
82
# File 'lib/brakeman/processors/lib/call_conversion_helper.rb', line 73

def process_array_access array, args, original_exp = nil
  if args.length == 1 and integer? args.first
    index = args.first.value

    #Have to do this because first element is :array and we have to skip it
    array[1..-1][index] or original_exp
  else
    original_exp
  end
end

#process_hash_access(hash, index, original_exp = nil) ⇒ Object

Process hash access by returning the value associated with the given argument.


86
87
88
89
90
91
92
93
94
# File 'lib/brakeman/processors/lib/call_conversion_helper.rb', line 86

def process_hash_access hash, index, original_exp = nil
  if value = hash_access(hash, index)
    value # deep_clone?
  elsif all_literals? hash, :hash
    safe_literal(hash.line)
  else
    original_exp
  end
end