Class: Brakeman::FindReturnValue

Inherits:
Object
  • Object
show all
Includes:
Util
Defined in:
lib/brakeman/processors/lib/find_return_value.rb

Overview

Attempts to determine the return value of a method.

Preferred usage:

Brakeman::FindReturnValue.return_value exp

Constant Summary

Constants included from Util

Util::ALL_PARAMETERS, Util::COOKIES, Util::COOKIES_SEXP, Util::PARAMETERS, Util::PARAMS_SEXP, Util::PATH_PARAMETERS, Util::QUERY_PARAMETERS, Util::REQUEST_ENV, Util::REQUEST_PARAMETERS, Util::REQUEST_PARAMS, Util::SESSION, Util::SESSION_SEXP

Class Method Summary collapse

Instance Method Summary collapse

Methods included from Util

#array?, #block?, #call?, #camelize, #contains_class?, #context_for, #cookies?, #false?, #file_by_name, #file_for, #github_url, #hash?, #hash_access, #hash_insert, #hash_iterate, #integer?, #make_call, #node_type?, #number?, #params?, #pluralize, #regexp?, #relative_path, #request_env?, #request_value?, #result?, #set_env_defaults, #sexp?, #string?, #symbol?, #table_to_csv, #template_path_to_name, #true?, #truncate_table, #underscore

Constructor Details

#initializeFindReturnValue

Returns a new instance of FindReturnValue.



18
19
20
21
# File 'lib/brakeman/processors/lib/find_return_value.rb', line 18

def initialize
  @uses_ivars = false
  @return_values = []
end

Class Method Details

.return_value(exp, env = nil) ⇒ Object

Returns a guess at the return value of a given method or other block of code.

If multiple return values are possible, returns all values in an :or Sexp.



14
15
16
# File 'lib/brakeman/processors/lib/find_return_value.rb', line 14

def self.return_value exp, env = nil
  self.new.get_return_value exp, env
end

Instance Method Details

#find_explicit_return_values(exp) ⇒ Object

Searches expression for return statements.



59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
# File 'lib/brakeman/processors/lib/find_return_value.rb', line 59

def find_explicit_return_values exp
  todo = [exp]

  until todo.empty?
    current = todo.shift

    @uses_ivars = true if node_type? current, :ivar

    if node_type? current, :return
      @return_values << current.value unless current.value.nil?
    elsif sexp? current
      todo = current[1..-1].concat todo
    end
  end
end

#get_return_value(exp, env = nil) ⇒ Object

Find return value of Sexp. Takes an optional starting environment.



28
29
30
31
32
33
# File 'lib/brakeman/processors/lib/find_return_value.rb', line 28

def get_return_value exp, env = nil
  process_method exp, env
  value = make_return_value
  value.original_line = exp.line
  value
end

#last_value(exp) ⇒ Object

Determines the “last value” of an expression.



76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
# File 'lib/brakeman/processors/lib/find_return_value.rb', line 76

def last_value exp
  case exp.node_type
  when :rlist, :block, :scope, Sexp
    last_value exp.last
  when :if
    then_clause = exp.then_clause
    else_clause = exp.else_clause

    if then_clause.nil?
      last_value else_clause
    elsif else_clause.nil?
      last_value then_clause
    else
      true_branch = last_value then_clause
      false_branch = last_value else_clause

      if true_branch and false_branch
        value = make_or(true_branch, false_branch)
        value.original_line = value.rhs.line
        value
      else #Unlikely?
        true_branch or false_branch
      end
    end
  when :lasgn, :iasgn
    exp.rhs
  when :return
    exp.value
  else
    exp.original_line = exp.line unless exp.original_line
    exp
  end
end

#make_or(lhs, rhs) ⇒ Object



110
111
112
113
114
115
116
117
# File 'lib/brakeman/processors/lib/find_return_value.rb', line 110

def make_or lhs, rhs
  #Better checks in future
  if lhs == rhs
    lhs
  else
    Sexp.new(:or, lhs, rhs)
  end
end

#make_return_valueObject

Turns the array of return values into an :or Sexp



120
121
122
123
124
125
126
127
128
129
130
131
132
133
# File 'lib/brakeman/processors/lib/find_return_value.rb', line 120

def make_return_value
  @return_values.compact!
  @return_values.uniq!

  if @return_values.empty?
    Sexp.new(:nil)
  elsif @return_values.length == 1
    @return_values.first
  else
    @return_values.reduce do |value, sexp|
      make_or value, sexp
    end
  end
end

#process_method(exp, env = nil) ⇒ Object

Process method (or, actually, any Sexp) for return value.



36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
# File 'lib/brakeman/processors/lib/find_return_value.rb', line 36

def process_method exp, env = nil
  exp = Brakeman::AliasProcessor.new.process_safely exp, env

  find_explicit_return_values exp

  if node_type? exp, :methdef, :selfdef, :defn, :defs
    body = exp.body

    unless body.empty?
      @return_values << last_value(body)
    else
      Brakeman.debug "FindReturnValue: Empty method? #{exp.inspect}"
    end
  elsif exp
    @return_values << last_value(exp)
  else
     Brakeman.debug "FindReturnValue: Given something strange? #{exp.inspect}"
  end

  exp
end

#uses_ivars?Boolean

Returns:

  • (Boolean)


23
24
25
# File 'lib/brakeman/processors/lib/find_return_value.rb', line 23

def uses_ivars?
  @uses_ivars
end