Class: Brakeman::CallIndex

Inherits:
Object show all
Defined in:
lib/brakeman/call_index.rb

Overview

Stores call sites to look up later.

Instance Method Summary collapse

Constructor Details

#initialize(calls) ⇒ CallIndex

Initialize index with calls from FindAllCalls


7
8
9
10
11
12
# File 'lib/brakeman/call_index.rb', line 7

def initialize calls
  @calls_by_method = Hash.new
  @calls_by_target = Hash.new

  index_calls calls
end

Instance Method Details

#find_calls(options) ⇒ Object

Find calls matching specified option hash.

Options:

* :target - symbol, array of symbols, or regular expression to match target(s)
* :method - symbol, array of symbols, or regular expression to match method(s)
* :chained - boolean, whether or not to match against a whole method chain (false by default)
* :nested - boolean, whether or not to match against a method call that is a target itself (false by default)

22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
# File 'lib/brakeman/call_index.rb', line 22

def find_calls options
  target = options[:target] || options[:targets]
  method = options[:method] || options[:methods]
  nested = options[:nested]

  if options[:chained]
    return find_chain options
  #Find by narrowest category
  elsif target and method and target.is_a? Array and method.is_a? Array
    if target.length > method.length
      calls = filter_by_target calls_by_methods(method), target
    else
      calls = calls_by_targets(target)
      calls = filter_by_method calls, method
    end

  #Find by target, then by methods, if provided
  elsif target
    calls = calls_by_target target

    if calls and method
      calls = filter_by_method calls, method
    end

  #Find calls with no explicit target
  #with either :target => nil or :target => false
  elsif options.key? :target and not target and method
    calls = calls_by_method method
    calls = filter_by_target calls, nil

  #Find calls by method
  elsif method
    calls = calls_by_method method
  else
    notify "Invalid arguments to CallCache#find_calls: #{options.inspect}"
  end

  return [] if calls.nil?

  #Remove calls that are actually targets of other calls
  #Unless those are explicitly desired
  calls = filter_nested calls unless nested

  calls
end

#index_calls(calls) ⇒ Object


96
97
98
99
100
101
102
103
104
105
106
# File 'lib/brakeman/call_index.rb', line 96

def index_calls calls
  calls.each do |call|
    @calls_by_method[call[:method]] ||= []
    @calls_by_method[call[:method]] << call

    unless call[:target].is_a? Sexp
      @calls_by_target[call[:target]] ||= []
      @calls_by_target[call[:target]] << call
    end
  end
end

#remove_indexes_by_class(classes) ⇒ Object


82
83
84
85
86
87
88
89
90
91
92
93
94
# File 'lib/brakeman/call_index.rb', line 82

def remove_indexes_by_class classes
  @calls_by_method.each do |name, calls|
    calls.delete_if do |call|
      call[:location][:type] == :class and classes.include? call[:location][:class]
    end
  end

  @calls_by_target.each do |name, calls|
    calls.delete_if do |call|
      call[:location][:type] == :class and classes.include? call[:location][:class]
    end
  end
end

#remove_template_indexes(template_name = nil) ⇒ Object


68
69
70
71
72
73
74
75
76
77
78
79
80
# File 'lib/brakeman/call_index.rb', line 68

def remove_template_indexes template_name = nil
  @calls_by_method.each do |name, calls|
    calls.delete_if do |call|
      from_template call, template_name
    end
  end

  @calls_by_target.each do |name, calls|
    calls.delete_if do |call|
      from_template call, template_name
    end
  end
end