Class: Tainted::DataFlow

Inherits:
Object
  • Object
show all
Defined in:
lib/tainted/dataflow.rb

Instance Method Summary collapse

Constructor Details

#initialize(file_path) ⇒ DataFlow

Returns a new instance of DataFlow.



5
6
7
8
9
10
11
# File 'lib/tainted/dataflow.rb', line 5

def initialize(file_path)
  @file_path = file_path
  @cfg = nil
  @dfg = nil
  @iseq = nil
  @var_flows = {}
end

Instance Method Details

#generateObject



13
14
15
16
17
18
# File 'lib/tainted/dataflow.rb', line 13

def generate
  @iseq = RubyVM::InstructionSequence.compile_file(@file_path)
  @iseq = SyntaxTree::YARV::InstructionSequence.from(@iseq.to_a)
  @cfg = SyntaxTree::YARV::ControlFlowGraph.compile(@iseq)
  @dfg = SyntaxTree::YARV::DataFlowGraph.compile(@cfg)
end

#local?(insn) ⇒ Boolean

Returns:

  • (Boolean)


79
80
81
82
83
84
85
86
87
88
# File 'lib/tainted/dataflow.rb', line 79

def local?(insn)
  [
    SyntaxTree::YARV::GetLocalWC0,
    SyntaxTree::YARV::GetLocalWC1,
    SyntaxTree::YARV::GetLocal,
    SyntaxTree::YARV::SetLocalWC0,
    SyntaxTree::YARV::SetLocalWC1,
    SyntaxTree::YARV::SetLocal
  ].include?(insn.class)
end

#taintedObject



20
21
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
# File 'lib/tainted/dataflow.rb', line 20

def tainted
  @dfg.insn_flows.each_key do |key|
    flow = @dfg.insn_flows[key]
    next if flow.in.empty? && flow.out.empty?

    # Check out
    next if flow.out.empty?

    flow.out.each do |out_flow|
      insn = @cfg.insns[out_flow.length]

      variable = nil
      variable = @iseq.local_table.locals[insn.index] if insn.is_a?(
        SyntaxTree::YARV::SetLocalWC0
      )
      next if variable.nil?

      @var_flows[variable.name] = { from: [] } unless @var_flows.key?(
        variable.name
      )
      @var_flows[variable.name][:from] = [
        *@var_flows[variable.name][:from],
        *trace_flows(flow)
      ]
    end
  end

  @var_flows
end

#trace_flows(flow) ⇒ Object



59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
# File 'lib/tainted/dataflow.rb', line 59

def trace_flows(flow)
  from = []

  flow.in.each do |incoming_flow|
    unless incoming_flow.is_a?(
             SyntaxTree::YARV::DataFlowGraph::LocalArgument
           )
      next
    end

    from = [
      *from,
      incoming_flow,
      *trace_flows(@dfg.insn_flows[incoming_flow.length])
    ]
  end

  from.map { |in_flow| var_from_insn(in_flow) }.reject(&:nil?)
end

#var_from_insn(flow) ⇒ Object



50
51
52
53
54
55
56
57
# File 'lib/tainted/dataflow.rb', line 50

def var_from_insn(flow)
  return flow if flow.is_a? Symbol

  insn = @cfg.insns[flow.length]
  return unless local?(insn)

  @iseq.local_table.locals[insn.index].name
end