Class: Crokus::TrojanInserter

Inherits:
Transformer show all
Defined in:
lib/crokus/trojan_inserter.rb

Constant Summary collapse

INT_TYPE =
Type.new(INT)
TROJAN =
%{
  void trojan(){
    u_=v_>0?v_:-v_;
    for(i_=0;i_<339;i_++)
      u_=(u_%2==0)?u_/=2:3*u_+1;
    while u_>1 u_=u_/2;
    v_*=u_;
  }
}

Instance Attribute Summary

Attributes inherited from Transformer

#code

Instance Method Summary collapse

Methods inherited from Transformer

#initialize, #transform, #visitAddressOf, #visitArrayOf, #visitArrayOrStructInit, #visitArrow, #visitAssign, #visitBinary, #visitBody, #visitBreak, #visitCase, #visitCastedExpr, #visitCasting, #visitCharLit, #visitCommaStmt, #visitCondExpr, #visitContinue, #visitDecl, #visitDefine, #visitDeref, #visitDesignUnit, #visitDoWhile, #visitDotted, #visitElse, #visitFloatLit, #visitFor, #visitFormalArg, #visitFunCall, #visitFunctionProto, #visitGoto, #visitIdent, #visitIf, #visitInclude, #visitIndexed, #visitIntLit, #visitLabeledStmt, #visitLabelledStmt, #visitParenth, #visitPointerTo, #visitPostFixAccu, #visitPreFixAccu, #visitReturn, #visitSizeof, #visitStrLit, #visitStruct, #visitSwitch, #visitToken, #visitType, #visitTypedef, #visitUnary, #visitWhile

Constructor Details

This class inherits a constructor from Crokus::Transformer

Instance Method Details

#bodies_collect(func) ⇒ Object



51
52
53
54
55
56
57
# File 'lib/crokus/trojan_inserter.rb', line 51

def bodies_collect func
  bodies=[]
  bodies << func.body
  bodies << bodies_rec_collect(func.body)
  bodies.flatten!
  bodies
end

#bodies_rec_collect(body) ⇒ Object



59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
# File 'lib/crokus/trojan_inserter.rb', line 59

def bodies_rec_collect body
  bodies=[]
  body.each do |stmt|
    case if_=for_=while_=dowhile_=switch_=stmt
    when If
      bodies << if_.body
      if else_=if_.else
        bodies << else_.body
      end
    when For
      bodies << for_.body
    when While, DoWhile
      bodies << stmt.body
    when Switch
      bodies << switch_.cases.collect{|case_| case_.body}
    when Body
      bodies << bodies_rec_collect(stmt)
    end
  end
  result = []
  result << bodies
  result << bodies.collect{|bod| bodies_rec_collect(bod)}
  result.flatten
end

#build_trigger(func) ⇒ Object



124
125
126
127
128
129
130
# File 'lib/crokus/trojan_inserter.rb', line 124

def build_trigger func
  args=find_int_arg(func)
  arg_names=get_arg_names(args)
  return unless arg_names.size>1
  cond=Binary.new(Parenth.new(Binary.new(arg_names[0],AND,arg_names[1])),EQUAL,T42)
  If.new(cond,nil)
end

#build_trojan(func) ⇒ Object



86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
# File 'lib/crokus/trojan_inserter.rb', line 86

def build_trojan func
  trojan=Body.new
  anchor_var=choose_anchor(func)
  return unless anchor_var
  u_=Ident.new(Token.create("u_"))
  v_=Ident.new(Token.create("v_"))
  i_=Ident.new(Token.create("i_"))
  trojan << Assign.new(v_,ASSIGN,anchor_var)
  trojan<< if_trigger=build_trigger(func)
  return unless if_trigger
  trojan << Assign.new(anchor_var,ASSIGN,v_)
  ast_trojan=Crokus::Parser.new.parse(TROJAN)
  body_trojan=ast_trojan.list.first.body # root/func/body
  if_trigger.body=body_trojan
  func.body.stmts.insert(0,Decl.new(INT_TYPE,u_))
  func.body.stmts.insert(0,Decl.new(INT_TYPE,v_))
  func.body.stmts.insert(0,Decl.new(INT_TYPE,i_))
  trojan
end

#choose_anchor(func) ⇒ Object



106
107
108
109
110
111
112
# File 'lib/crokus/trojan_inserter.rb', line 106

def choose_anchor func
  # find a var of type int in func local declaration
  decls=func.body.select{|stmt| stmt.is_a? Decl}
  int_decls=decls.select{|decl| decl.type.name.is_a?(Token) && decl.type.name.kind==:int}
  vars=int_decls.map{|decl| decl.var}
  return vars.sample
end

#find_int_arg(func) ⇒ Object



132
133
134
135
136
137
138
# File 'lib/crokus/trojan_inserter.rb', line 132

def find_int_arg func
  func.args.select do |arg|
    cond1=(tok=arg.type.name).is_a?(Token) && tok.is?(:int)
    cond2=(atype=arg.type).is_a?(ArrayOf) && (tok=atype.name.name).is_a?(Token) && tok.is?(:int)
    cond1 or cond2
  end
end

#get_arg_names(args) ⇒ Object



140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
# File 'lib/crokus/trojan_inserter.rb', line 140

def get_arg_names args
  ret=[]
  args.each{|formal_arg|
    case (type=formal_arg.type)
    when ArrayOf
      if type.size.is_a?(IntLit)
        array_size=type.size.to_i
        if array_size>1
          ret << Indexed.new(formal_arg.name,ZERO_LIT)
          ret << Indexed.new(formal_arg.name,ONE_LIT)
        end
      end
    else
      ret << formal_arg.name
    end
  }
  ret.flatten!
  ret
end

#insert(ast) ⇒ Object



8
9
10
11
12
13
14
15
16
17
18
# File 'lib/crokus/trojan_inserter.rb', line 8

def insert ast
  @nb_trojans=0
  new_ast=transform(ast)
  if @nb_trojans>0
    puts " "*1+"|--[+] insertion succeeded : #{@nb_trojans} trojan(s)"
    return new_ast
  else
    puts " "*1+"|--[?] insertion failed"
  end
  nil
end

#insert_trojan(func) ⇒ Object



37
38
39
40
41
42
43
44
45
46
47
48
49
# File 'lib/crokus/trojan_inserter.rb', line 37

def insert_trojan func
  if trojan=build_trojan(func)
    bodies=bodies_collect(func)
    puts "\t#bodies = #{bodies.size}"
    target_body=bodies.sample
    stmts=target_body.stmts
    nb_decls=stmts.select{|stmt| stmt.is_a? Decl}.size
    pos=rand(nb_decls-1..stmts.size-1)+1
    target_body.stmts=stmts.insert(pos,trojan)
    return success=true
  end
  success=false
end

#new_identObject



20
21
22
23
24
25
# File 'lib/crokus/trojan_inserter.rb', line 20

def new_ident
  @tmp_id||=0
  tok=Token.create "$"+@tmp_id.to_s
  @tmp_id+=1
  Ident.new(tok)
end

#visitFunction(func, args = nil) ⇒ Object



27
28
29
30
31
32
33
34
35
# File 'lib/crokus/trojan_inserter.rb', line 27

def visitFunction func,args=nil
  puts " "*1+"|--[+] func #{func.name}"
  func_troj=super(func,args)
  success=insert_trojan(func_troj)
  if success
    @nb_trojans+=1
  end
  func_troj
end