Class: Tainted::Static
- Inherits:
-
SyntaxTree::Visitor
- Object
- SyntaxTree::Visitor
- Tainted::Static
- Defined in:
- lib/tainted/static.rb
Instance Attribute Summary collapse
-
#offenses ⇒ Object
readonly
Returns the value of attribute offenses.
Instance Method Summary collapse
-
#initialize(sources, sinks) ⇒ Static
constructor
A new instance of Static.
- #parse_assign(node) ⇒ Object
- #parse_call(node) ⇒ Object
- #taint_status(var) ⇒ Object
- #visit(node) ⇒ Object
Constructor Details
#initialize(sources, sinks) ⇒ Static
Returns a new instance of Static.
7 8 9 10 11 12 13 |
# File 'lib/tainted/static.rb', line 7 def initialize(sources, sinks) super() @sources = sources @sinks = sinks @offenses = [] end |
Instance Attribute Details
#offenses ⇒ Object (readonly)
Returns the value of attribute offenses.
5 6 7 |
# File 'lib/tainted/static.rb', line 5 def offenses @offenses end |
Instance Method Details
#parse_assign(node) ⇒ Object
31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 |
# File 'lib/tainted/static.rb', line 31 def parse_assign(node) variable_name = node.target.value.value method_name = case node.value when SyntaxTree::CallNode node.value..value when SyntaxTree::ARef # (aref (vcall (ident "<method_name>"))) node.value.collection.value.value end return if method_name.nil? return unless @sources.include?(method_name&.to_sym) State.instance.var_dependencies[variable_name.to_sym][:tainted] = true end |
#parse_call(node) ⇒ Object
49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 |
# File 'lib/tainted/static.rb', line 49 def parse_call(node) arguments = node.arguments.arguments.parts taint_statuses = arguments.map { |arg| [arg, taint_status(arg.value.value.to_sym)] } method_name = node..value return unless @sinks.include?(method_name.to_sym) taint_statuses.each do |status| next unless status[1] @offenses << Offense.new(node, "Method `#{method_name}()` consuming tainted variable `#{status[0].value.value}`") end end |
#taint_status(var) ⇒ Object
65 66 67 68 69 70 71 72 73 74 75 76 77 |
# File 'lib/tainted/static.rb', line 65 def taint_status(var) if State.instance.var_dependencies[var].key?(:tainted) return State.instance.var_dependencies[var][:tainted] end tainted = false unless State.instance.var_dependencies[var][:from].empty? State.instance.var_dependencies[var][:from].each do |from| tainted ||= taint_status(from) end end State.instance.var_dependencies[var][:tainted] = tainted end |
#visit(node) ⇒ Object
15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 |
# File 'lib/tainted/static.rb', line 15 def visit(node) nodes = node.child_nodes[0].child_nodes # First visit all assignments # mark tainted variables nodes .select { |child| child.is_a?(SyntaxTree::Assign) } .each { |child| parse_assign(child) } # Visit all call nodes # check if a tainted variable is passed to it nodes .select { |child| child.is_a?(SyntaxTree::CallNode) } .each { |child| parse_call(child) } end |