def check_value(ast_tree, ext_index, bock_item_index, var_name, func_name): Cast = c_ast.Cast( c_ast.Typename( None, [], c_ast.PtrDecl([], c_ast.TypeDecl(None, [], c_ast.IdentifierType(['void'])))), c_ast.ID(var_name)) func_call = c_ast.FuncCall( c_ast.ID('check_value'), c_ast.ExprList([ c_ast.UnaryOp('&', c_ast.ID('global_log')), Cast, c_ast.Constant('string', '"' + var_name + '"'), c_ast.Constant('string', '"' + func_name + '"'), c_ast.Constant('int', str(len(var_name))), c_ast.Constant('int', str(len(func_name))) ])) new_node = c_ast.If( c_ast.BinaryOp('==', func_call, c_ast.Constant('int', '0')), c_ast.Compound([ c_ast.FuncCall( c_ast.ID('printf'), c_ast.ExprList([ c_ast.Constant('string', '"%s\\n"'), c_ast.Constant('string', '"Attack Detected"') ])), c_ast.FuncCall(c_ast.ID('exit'), c_ast.ExprList([c_ast.Constant('int', '1')])) ]), None) return merge_ast_tree(ast_tree, ext_index, bock_item_index, new_node, "insert_before")
def generate_array_ref(decl, subscript_base): """ Generate ArrayRef from Decl. For example: int array[1][2][3]; Should become: array[subscript_base_i0][subscript_base_i1][subscript_base_i2] """ if isinstance(decl.type.type, c_ast.ArrayDecl): # Multi-dimensional, recurse name = generate_array_ref(decl.type, subscript_base) # Subscript index is one more than the node below subscript_index = int(name.subscript.name[-1]) + 1 if subscript_index >= 10: raise Exception( "Only single-digit subscript indicies currently supported. Please fix." ) else: # Single or last dimension name = c_ast.ID(decl.type.type.declname) # Base node has subscript index of 0 subscript_index = 0 # Create ArrayRef array_ref = c_ast.ArrayRef( name, c_ast.ID("%s%d" % (subscript_base, subscript_index))) return array_ref
def __for_loop(self, depth: int) -> c_ast.For: """ A helper function to construct a for loop corresponding to allocating one dimension of an array. Recursively calls itself to generate next levels or generates an initialisation line if it is the last level. Example: for(i_2 = 0; i_2 < N; i_2++) { ... } :param depth: :return: C-ast.For """ i = self.counter_prefix + str(depth) init = c_ast.DeclList([ c_ast.Decl(c_ast.ID(i), [], [], [], c_ast.TypeDecl(i, [], c_ast.IdentifierType(['int'])), c_ast.Constant('int', '0'), '') ]) cond = c_ast.BinaryOp('<', c_ast.ID(i), self.sizes[depth]) nxt = c_ast.Assignment('++', c_ast.ID(i), None) stmt = c_ast.Compound([]) if depth < len(self.sizes) - 1: stmt.block_items = [ self.__malloc_assign(depth + 1), self.__for_loop(depth + 1) ] else: stmt.block_items = [self.initialiser(depth + 1)] return c_ast.For(init, cond, nxt, stmt)
def __malloc(self, depth: int) -> c_ast.FuncCall: """ A helper function to generate the call of malloc function with proper arguments. Note that a constant of 2 is added to the number of allocated cells. This is meant to compensate minor errors in size estimation. Example: malloc((N + 2) * sizeof(int*)) :param depth: Which dimension of the array we want to allocate. Used to generate the argument of sizeof(). :return: c_ast.FuncCall """ size_expr = \ c_ast.BinaryOp( '+', self.sizes[depth], c_ast.Constant('int', '2') ) sizeof = \ c_ast.FuncCall( c_ast.ID('sizeof'), c_ast.ExprList([c_ast.ID(self.dtype.name + '*' * (len(self.sizes) - depth - 1))]) ) arg = c_ast.BinaryOp('*', size_expr, sizeof) return c_ast.FuncCall(c_ast.ID('malloc'), c_ast.ExprList([arg]))
def createMain(self): #Main Function #Declaration z1 = c_ast.TypeDecl('args',[],c_ast.IdentifierType(['int'])) args = c_ast.Decl('args',[],[],[],z1,None,None) z2= c_ast.PtrDecl([],c_ast.TypeDecl('argv',[],c_ast.IdentifierType(['char']))) z3=c_ast.ArrayDecl(z2,None,[]) argv = c_ast.Decl('argv',[],[],[],z3,None,None) params=c_ast.ParamList([args,argv]) mainDec=c_ast.FuncDecl(params,c_ast.TypeDecl('main',[],c_ast.IdentifierType(['int']))) # insertTest(functionName,varVals,varTypes) #Body ##Signal sigalrm=c_ast.ID(name="14") funcCast=c_ast.TypeDecl(declname = None,quals=[],type=c_ast.IdentifierType(['void'])) paramCast=c_ast.ParamList([c_ast.Typename(name=None,quals=[],type=c_ast.TypeDecl(declname = None,quals=[],type=c_ast.IdentifierType(['int'])))]) typeFunc=c_ast.PtrDecl(type=c_ast.FuncDecl(paramCast,funcCast),quals=[]) kchild=c_ast.Cast(to_type=c_ast.Typename(name=None, quals=[],type=typeFunc),expr=c_ast.ID(name="kill_child")) expressList = [sigalrm,kchild] signalStmt=c_ast.FuncCall(c_ast.ID(name="signal"),c_ast.ExprList(expressList)) ##Return returnStmt=c_ast.Return(c_ast.Constant(type="int",value="0")) comp=c_ast.Compound([signalStmt,returnStmt]) return c_ast.FuncDef(mainDec,None,comp)
def astVeriNon(): veryidt = c_ast.IdentifierType(['int']) verytype = c_ast.TypeDecl('rand', [], veryidt) bifunc = c_ast.FuncCall(c_ast.ID('__VERIFIER_nondet'), None) verybina = c_ast.BinaryOp('%', bifunc, c_ast.ID('N')) simdecl = c_ast.Decl('rand', [], [], [], verytype, verybina, None, None) return simdecl
def create_capture_node(new_vars, var, index, while_body): """Create an assignment capture node (new_vars = var)""" tab = [] if isinstance(while_body[index], (c_ast.While, c_ast.If)): tab.append(c_ast.Assignment("=", c_ast.ID(new_vars[1]), while_body[index].cond)) tab.append(c_ast.Assignment("=", c_ast.ID(new_vars[0]), c_ast.ID(var))) return tab
def replacer(e: Expression) -> Optional[Expression]: if e in replace_cand_set: if should_make_ptr: return ca.UnaryOp("*", ca.ID(var)) else: return ca.ID(var) return None
def pre_argument(self, name): commands = [] commands.append( _generate_decl( name + '_int', c_ast.TypeDecl(name + '_int', [], c_ast.IdentifierType(['unsigned', 'int'])))) commands.append(_generate_read(name + '_int')) commands.append( c_ast.Assignment('|=', c_ast.ID(name + '_int'), c_ast.Constant('int', PTR_OFFSET))) commands.append( c_ast.Decl( name, [], [], [], c_ast.PtrDecl( [], c_ast.TypeDecl(name, [], c_ast.IdentifierType(['void'])), ), c_ast.Cast( c_ast.Typename( None, [], c_ast.PtrDecl([], c_ast.TypeDecl( None, [], c_ast.IdentifierType(['void'])))), c_ast.ID(name + '_int')), [])) return commands
def make_klee_symbolic(variable_name, trackingName): arg1 = c_ast.UnaryOp(op='&', expr=c_ast.ID(variable_name)) arg2 = c_ast.UnaryOp(op='sizeof', expr = c_ast.Typename(name=None, quals =[], type= c_ast.TypeDecl(declname=None,quals=[], type=c_ast.IdentifierType(names=['int'])))) arg3 = c_ast.Constant(type='string', value='\"'+ trackingName +'\"') return c_ast.FuncCall(name=c_ast.ID(name = "klee_make_symbolic"), args=c_ast.ExprList(exprs=[arg1,arg2,arg3]))
def max_set(exprs): """ Transforms an iterable of expressions into a C expression which will evalueate to its maximum. MAX(x, y) macro must be included to the C program. If there are multiple integer values in the iterable, only the greatest one is preserved (see remove_non_extreme_numbers) Example: ['3', '6', '7', 'N', 'K'] -> 'MAX(MAX(7, N), 'K')' :param exprs: An iterable of expressions as strings :return: Output string """ # noinspection PyShadowingNames def max_set_recur(exprs): if len(exprs) == 0: return None if len(exprs) == 1: return exprs[0] else: half = int(len(exprs) / 2) a = max_set_recur(exprs[:half]) b = max_set_recur(exprs[half:]) return c_ast.FuncCall(c_ast.ID('MAX'), c_ast.ExprList([a, b])) if type(exprs) is str: return c_ast.ID(exprs) exprs = remove_non_extreme_numbers(exprs, leave_min=False) exprs = [c_ast.ID(e) for e in exprs] return max_set_recur(exprs)
def children(self): nodelist = [] if self.adviceBody is not None: nodelist.append(("adviceBody", c_ast.ID(self.adviceBody))) if self.identifier is not None: nodelist.append(("identifier", c_ast.ID(self.identifier))) return tuple(nodelist)
def rename_array_args(funcdef): """ Rename and copy arrays passed as arguments to funcdef. """ # For each argument for param in funcdef.decl.type.args.params: if isinstance(param.type, c_ast.ArrayDecl): # Rename and copy array arg_decl = copy.deepcopy(param) # Rename array v = inline.RenameVisitor() v.new_visit(get_decl_name(param), get_decl_name(param) + "_rename", funcdef.body) # Add copy and declarations funcdef.body.block_items = rename_array_decl( arg_decl) + funcdef.body.block_items elif isinstance(param.type, c_ast.TypeDecl): # Simple variable passing, don't need to handle pass elif isinstance(param.type, c_ast.PtrDecl): # Don't copy pointer arguments return """ Param of form: type *var is copied in the function body using: type var_rename _temp = *var; type *var_rename = &var_rename_temp; """ # General pointer arguments old_name = get_decl_name(param) new_name = old_name + "_rename" temp_name = new_name + "_temp" # Rename variable use in function body v = inline.RenameVisitor() v.new_visit(old_name, new_name, funcdef.body) # type var_rename_temp = *var; decl1 = c_ast.Decl( temp_name, None, None, None, c_ast.TypeDecl(temp_name, None, param.type.type.type), c_ast.UnaryOp('*', c_ast.ID(old_name)), None) # type *var_rename = &var_rename_temp; decl2 = c_ast.Decl( new_name, None, None, None, c_ast.PtrDecl([], c_ast.TypeDecl(new_name, None, param.type.type.type)), c_ast.UnaryOp('&', c_ast.ID(temp_name)), None) # Insert into function body funcdef.body.block_items.insert(0, decl2) funcdef.body.block_items.insert(0, decl1) else: print_node(param) param.show(nodenames=True, showcoord=True) raise Exception( "Unhandled argument type %s. Implement or verify that it can be ignored." % (type(param.type)))
def merge_libs_calls(self, node): start = -1 end = -1 argumented_client = None argumented_lib = None LibCV = LibCallHunter(self.lib_name) if isinstance(node, c_ast.If): if isinstance(node.iftrue, c_ast.Compound): checking_blocks = node.iftrue.block_items elif isinstance(node, c_ast.FuncDef): checking_blocks = node.body.block_items elif isinstance(node, c_ast.Compound): checking_blocks = node.block_items else: checking_blocks = [] new_leaf = set() mulitiple_call = False for index in range(len(checking_blocks)): LibCV.use_lib = False block = checking_blocks[index] LibCV.visit(block) if LibCV.use_lib: for lib in LibCV.lib_node: l_object = self.node_dict.get(lib, None) if l_object is None: l_object, _ = self.create_ClientContextNode( lib, lib, None, lib, None) self.node_dict[node] = l_object new_leaf.add(l_object) if (start == -1): start = index if (end < index): end = index if (len(LibCV.lib_node) > 1): mulitiple_call = True if (end > start) or (start == end and mulitiple_call): argumented_lib = c_ast.Compound( block_items=checking_blocks[start:end + 1]) argumented_client = copy.deepcopy(node) if isinstance(argumented_client, c_ast.If): if isinstance(argumented_client.iftrue, c_ast.Compound): blocks = argumented_client.iftrue.block_items argumented_client.iftrue.block_items = blocks[:start] + [ c_ast.FuncCall(name=c_ast.ID(name="CLEVER_DELETE"), args=None) ] + blocks[end + 1:] elif isinstance(argumented_client, c_ast.FuncDef): blocks = argumented_client.body.block_items argumented_client.body.block_items = blocks[:start] + [ c_ast.Compound(block_items=[ c_ast.FuncCall(name=c_ast.ID(name="CLEVER_DELETE"), args=None) ] + checking_blocks[start:end + 1]) ] + blocks[end + 1:] return start, end, argumented_lib, argumented_client, new_leaf
def astAssiDef(isr): larr = c_ast.ArrayRef( c_ast.ID('deferral'), c_ast.Constant( 'int', str(int(isr) - 1))) # the second param of Constant is String rarr = c_ast.UnaryOp('&', c_ast.ID('deferral_' + isr)) assi = c_ast.Assignment('=', larr, rarr) return assi
def create_capture_node(new_vars, var, i, while_node): tab = [] tab.append(c_ast.Assignment("=", c_ast.ID(new_vars[0]), c_ast.ID(var))) if iscond(while_node.stmt.block_items[i]): tab.append( c_ast.Assignment("=", c_ast.ID(new_vars[1]), while_node.stmt.block_items[i].cond)) tab.reverse() return tab
def add_jump_guard(ast_to_guard, phase_var, round_var, label): guarded_ast = c_ast.If( c_ast.BinaryOp( '&&', c_ast.BinaryOp('==', c_ast.ID(phase_var), c_ast.ID('PHASE')), c_ast.BinaryOp('==', c_ast.ID(round_var), c_ast.ID(label))), ast_to_guard, None) return c_ast.Compound([guarded_ast])
def offsetof(self, struct_name, name): return c_ast.FuncCall( c_ast.ID('offsetof'), c_ast.ExprList([ c_ast.Typename( None, [], c_ast.TypeDecl(None, [], c_ast.Struct(struct_name, None))), c_ast.ID(name) ]))
def children(self): nodelist = [] if self.pname is not None: nodelist.append(("pname", c_ast.ID(self.pname))) if self.args is not None: nodelist.append(("args", self.args)) if self.o is not None: nodelist.append(("o", c_ast.ID(self.o))) return tuple(nodelist)
def astDequeue(queue): #the type of exprs is String exdeq = [c_ast.ID(queue)] exprs = c_ast.ExprList(exdeq) dequeue = c_ast.FuncCall(c_ast.ID('Dequeue'), exprs) # astseq.ext[167].body.block_items[2].args.exprs[0] = c_ast.ID(queue) # dequeue=astseq.ext[167].body.block_items[2] # print ("\033[1;5;32;45;1mFuncCall Dequeue\033[0m") # dequeue.show() return dequeue
def makeScopeOutLog(coord): (file, line) = getLocation(coord) return c_ast.FuncCall( c_ast.ID('fprintf'), c_ast.ExprList([ c_ast.ID('stderr'), c_ast.Constant('string', '"{0}:{1}:scope_out\\n"'.format(file, line)) ]))
def visit_FuncDef(self, node): label = c_ast.Label("predict_exec_time", c_ast.EmptyStatement()) decl = c_ast.Decl("exec_time", None, None, None, c_ast.TypeDecl("exec_time", None, c_ast.IdentifierType(["float"])), None, None) assignment = c_ast.Assignment('=', c_ast.ID("exec_time"), c_ast.Constant("int", 0)) ret = c_ast.Return(c_ast.ID("exec_time")) compound = c_ast.Compound([label, decl, assignment, ret]) node.body.block_items.append(compound)
def makeFuncCallLog(func): return c_ast.FuncCall( c_ast.ID('fprintf'), c_ast.ExprList([ c_ast.ID('stderr'), c_ast.Constant( 'string', '"{0}:{1}:call({2})\\n"'.format(func['file'], func['line'], func['name'])) ]))
def set_outdated(ast_tree, ext_index, bock_item_index, func_name): new_node = c_ast.FuncCall( c_ast.ID('set_outdated'), c_ast.ExprList([ c_ast.UnaryOp('&', c_ast.ID('global_log')), c_ast.Constant('string', '"' + func_name + '"'), c_ast.Constant('int', str(len(func_name))) ])) return merge_ast_tree(ast_tree, ext_index, bock_item_index, new_node, "insert_before")
def rename_bounds(self): """ Inserts a code fragment initializing program parameters. The actual values should be injected at compilation time (-D option in gcc) """ inits = [ c_ast.Assignment('=', c_ast.ID(n), c_ast.ID('PARAM_' + n.upper())) for n in self.bounds ] self.main.body.block_items[0:0] = inits
def astEnqueue(elemtype, queue): #the type of exprs is String exenq = [c_ast.Constant('int', elemtype), c_ast.ID(queue)] exprs = c_ast.ExprList(exenq) enqueue = c_ast.FuncCall(c_ast.ID('Enqueue'), exprs) # astseq.ext[166].body.block_items[5].args.exprs[0] = c_ast.Constant('int', elemtype) # astseq.ext[166].body.block_items[5].args.exprs[1] = c_ast.ID(queue) # enqueue=astseq.ext[166].body.block_items[5] # print ("\033[1;5;32;45;1mFuncCall Enqueue\033[0m") # enqueue.show() return enqueue
def createOutputIf(self, expr): expressList = [c_ast.Constant(type='int', value='0')] funcCall = c_ast.FuncCall(c_ast.ID(name="assert"), c_ast.ExprList(expressList)) if_all = c_ast.If(c_ast.BinaryOp(left=c_ast.ID(name='__out_var'), op='==', right=expr), c_ast.Compound([funcCall]), iffalse=None) return (if_all)
def new_fcall(fname, args): fname = c_ast.ID(fname) args_list = [] for arg in args: if isinstance(arg, str): args_list.append(c_ast.ID(arg)) else: args_list.append(arg) args = c_ast.ExprList(args_list) return c_ast.FuncCall(fname, args)
def insertTest(self,block,functionName,varVals,varTypes,timer): #Fork call cFork=c_ast.Assignment( lvalue=c_ast.ID(name='child_pid'), op='=', rvalue=c_ast.FuncCall( c_ast.ID(name='fork'), args=None)) #Child if self.functype=='int' or self.functype=="bool": printLeft=c_ast.Constant(type="char",value='"'+"%d" +'"') elif self.functype=='float' or self.functype=='double': printLeft=c_ast.Constant(type="char",value='"'+"%f" +'"') else: printLeft=c_ast.Constant(type="char",value='"'+"%d" +'"') expressList = list(c_ast.Constant(type=varTypes[i],value=str(varVals[i])) for i in range(len(varVals))) funcCall = c_ast.FuncCall(c_ast.ID(name=functionName),c_ast.ExprList(expressList)) expressList = [printLeft,funcCall] funcCall = c_ast.FuncCall(c_ast.ID(name="printf"),c_ast.ExprList(expressList)) funcCall2 = c_ast.FuncCall(c_ast.ID(name="exit"),c_ast.ExprList([c_ast.Constant(type='int',value='0')])) #Parent cAlarm=c_ast.FuncCall( c_ast.ID(name='alarm'),c_ast.ExprList([c_ast.Constant(type='int',value=str(timer))])) cWait=c_ast.FuncCall( c_ast.ID(name='wait'),c_ast.ExprList([c_ast.ID(name='0')])) #IFs if_false= c_ast.If( c_ast.BinaryOp(left=c_ast.ID(name='child_pid'),op='==',right= c_ast.Constant(type='int',value='0')), c_ast.Compound([funcCall,funcCall2]),iffalse=None) if_ini=c_ast.If( c_ast.BinaryOp(left=c_ast.ID(name='child_pid'),op='>',right= c_ast.Constant(type='int',value='0')), c_ast.Compound([cAlarm,cWait]),iffalse=if_false) block.body.block_items.insert(1,if_ini) block.body.block_items.insert(1,cFork)
def visit_FuncCall(self, node): if isinstance(node, c_ast.FuncCall): if (node.name.name == "CLEVER_DELETE"): parent = self.parent_child.get(node, None) if parent is not None and isinstance(parent, c_ast.Compound): parent.block_items = [ c_ast.FuncCall(name=c_ast.ID(name="lib_old"), args=None), c_ast.FuncCall(name=c_ast.ID(name="lib_new"), args=None) ]