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 define_sizeof_modifier_type(t): # setup the toplevel call if t.get_typename(): argument_ast = t.get_reference()("storage") else: argument_ast = t.define("storage") prefix = "fffc_get_sizeof_" desired_name = CGenerator().visit(argument_ast) suffix = encode_hash(desired_name) function_name = prefix + suffix # build the underlying function call underlying_call = get_sizeof_pointer_to_type(t.underlying_type, c_ast.ID("storage")) # build this just as above, except with the call in place of the sizeof storage_tdecl = c_ast.Decl("storage", [], [], [], c_ast.PtrDecl([], argument_ast), None, None) func_tdecl = c_ast.TypeDecl( function_name, [], c_ast.IdentifierType(["long", "long", "unsigned"])) funcdecl = c_ast.FuncDecl(c_ast.ParamList([storage_tdecl]), func_tdecl) funcdef = c_ast.FuncDef( c_ast.Decl(function_name, [], [], [], funcdecl, None, None), None, c_ast.Compound([c_ast.Return(underlying_call)]), ) comment = "/* " + desired_name + "*/\n" kr_funcdecl = c_ast.FuncDecl(c_ast.ParamList([]), func_tdecl) return comment, kr_funcdecl, funcdef
def replace_funcs(self, dwarf_type): decls = [] defn = None # replace the underlying call for node in self.get_nodes(self.ast): if type(node) == c_ast.FuncCall: if node.name.name == self.underlying_mutator_name: if dwarf_type.get_typename(): ut = dwarf_type.get_reference()() else: ut = dwarf_type.define() underlying_mutator_name, underlying_decl_ast = make_mutator_decl_from_arg_type( ut, point=True, change_name=True) comment = "/* " + underlying_mutator_name + "*/\n" underlying_mutator_call = make_call_from_mutator_decl( "tmp", underlying_decl_ast) node.name = underlying_mutator_call.name # make this a k&r style decl, 'cause cheating is sometimes winning after all underlying_decl_ast.type.args = c_ast.ParamList([]) decls.append(comment + CGenerator().visit(underlying_decl_ast)) # build the decl and defn for node in self.get_nodes(self.ast): if type(node) == c_ast.FuncDef: if not defn: decl, defn = make_commented_mutator_defn(node) decls.append(decl) return decls, defn
def make_mutator_decl_from_arg_type(arg_type, generator=CGenerator(), seen={}, point=True, change_name=False): # memoize if arg_type in seen: return seen[arg_type] mut_name = "fffc_mutator_for_target_type" # change the type declname if change_name: change_declname(arg_type, "storage") # first, wrap the type in a pointer to match the necessary mutator semantics if point: arg_type_ptr = c_ast.PtrDecl([], arg_type) else: arg_type_ptr = arg_type # next, wrap that in a decl with the right name arg_decl = c_ast.ParamList( [c_ast.Decl("storage", [], [], [], arg_type_ptr, None, None)]) # next, generate the desired decl ret_type = c_ast.IdentifierType(["int"]) ret_decl = c_ast.TypeDecl(mut_name, [], ret_type) desired_decl = c_ast.FuncDecl(arg_decl, ret_decl) # now build the mangled name desired_name = generator.visit(desired_decl) suffix = encode_hash(desired_name) actual_name = "_Z_fffc_mutator_" + suffix desired_decl.type.declname = actual_name # build the output out = c_ast.Decl(actual_name, [], [], [], desired_decl, None, None) # save the result seen[arg_type] = (desired_name, out) # and go home return desired_name, out
def remove_input_port(func_def, ele_name, inports): func_def.decl.name = ele_name func_def.decl.type.type.declname = ele_name stmts = func_def.body.block_items new_stmts = [] port2args = {} for stmt in stmts: if type(stmt) == c_ast.Decl and type(stmt.init) == c_ast.FuncCall: funccall = stmt.init funcname = funccall.name.name if funcname in inports: if funccall.args: raise Exception( "Cannot pass an argument when retrieving data from an input port." ) myDecl = deepcopy(stmt) myDecl.init = None port2args[funcname] = myDecl continue new_stmts.append(stmt) func_def.body.block_items = new_stmts params = [port2args[x] for x in inports] print func_def.decl.type.args func_def.decl.type.args = c_ast.ParamList(params) func_def.show()
def visit_Decl(self, node): if not isinstance(node.type, c_ast.FuncDecl): return func_decl = node.type if not isinstance(func_decl.type, c_ast.TypeDecl) or not isinstance(func_decl.type.type, c_ast.IdentifierType) or func_decl.type.type.names != ['void']: self.functions[node.name] = node return_type=func_decl.type #node.return_type = return_type set_extra_attr(node, 'return_type', func_decl.type) #update declname it=return_type while it is not None: if isinstance(it, c_ast.TypeDecl): it.declname = 'return_of_the_jedi' it = None else: if hasattr(it, 'type'): it = it.type else: it = None func_decl.type = c_ast.TypeDecl(node.name, [], c_ast.IdentifierType(['void'])) result_type=deepcopy(return_type) result_type.type.names += '&' decl = create_simple_var(result_type, 'return_of_the_jedi', None) if func_decl.args is None: func_decl.args = c_ast.ParamList([]) #Handle the int f(void) case if len(func_decl.args.params) == 1 \ and isinstance(func_decl.args.params[0], c_ast.Typename) \ and isinstance(func_decl.args.params[0].type.type, c_ast.IdentifierType) \ and func_decl.args.params[0].type.type.names[0] == 'void': func_decl.args.params.pop() func_decl.args.params.append(decl)
def eliminateParams(self): self.params=c_ast.ParamList([]) mainDec=c_ast.Decl(name='mainFake',quals=[],init=None,bitsize=None,storage=[],funcspec=[],type=c_ast.FuncDecl(self.params,c_ast.TypeDecl('mainFake',[],c_ast.IdentifierType(['int'])))) self.main = c_ast.FuncDef(mainDec,None,self.main.body) for i,func in enumerate(self.ast.ext): if(isinstance(func,c_ast.FuncDef)): if func.decl.name == 'main': self.ast.ext[i]=self.main
def loop_func_params(): """ Shorthand for 'int set, long_long* values, clock_t* begin, clock_t* end' """ return c_ast.ParamList([ build_decl('set', 'int'), build_decl('values', 'long_long*'), build_decl('begin', 'clock_t*'), build_decl('end', 'clock_t*'), ])
def make_commented_mutator_defn(node, generator=CGenerator()): desired_name, decl = make_mutator_decl_from_arg_type( node.decl.type.args.params[0].type) node.decl = decl comment = "/* " + desired_name + "*/\n" defn = comment + generator.visit(node) # make this a k&r style decl, 'cause cheating is sometimes winning after all decl.type.args = c_ast.ParamList([]) decl = comment + generator.visit(decl) return decl, defn
def papi_instr() -> Tuple[List[c_ast.Node], List[c_ast.Node]]: """ :return: c_ast nodes representing the following code: exec(PAPI_start(set)); *begin = clock(); ... *end = clock(); exec(PAPI_stop(set, values)); """ papi_start = c_ast.FuncCall(c_ast.ID('PAPI_start'), c_ast.ParamList([c_ast.ID('set')])) papi_stop = c_ast.FuncCall(c_ast.ID('PAPI_stop'), c_ast.ParamList([c_ast.ID('set'), c_ast.ID('values')])) exec_start = c_ast.FuncCall(c_ast.ID('exec'), c_ast.ParamList([papi_start])) exec_stop = c_ast.FuncCall(c_ast.ID('exec'), c_ast.ParamList([papi_stop])) clock = c_ast.FuncCall(c_ast.ID('clock'), c_ast.ParamList([])) begin_clock = c_ast.Assignment('=', c_ast.UnaryOp('*', c_ast.ID('begin')), clock) end_clock = c_ast.Assignment('=', c_ast.UnaryOp('*', c_ast.ID('end')), clock) return [exec_start, begin_clock], [end_clock, exec_stop]
def define_sizeof_type_from_ast(argument_ast): prefix = "fffc_get_sizeof_" desired_name = CGenerator().visit(argument_ast) suffix = encode_hash(desired_name) function_name = prefix + suffix storage_tdecl = c_ast.Decl("storage", [], [], [], c_ast.PtrDecl([], argument_ast), None, None) func_tdecl = c_ast.TypeDecl( function_name, [], c_ast.IdentifierType(["long", "long", "unsigned"])) funcdecl = c_ast.FuncDecl(c_ast.ParamList([storage_tdecl]), func_tdecl) funcdef = c_ast.FuncDef( c_ast.Decl(function_name, [], [], [], funcdecl, None, None), None, c_ast.Compound([ c_ast.Return( c_ast.UnaryOp("sizeof", c_ast.UnaryOp("*", c_ast.ID("storage")))) ]), ) comment = "/* " + desired_name + "*/\n" kr_funcdecl = c_ast.FuncDecl(c_ast.ParamList([]), func_tdecl) return comment, kr_funcdecl, funcdef
def create_ClientContextNode(self, node, lib_node, parent, raw_lib_node, known_child=None, leaf=None): global is_MLCCheker hook_installed = False should_remove = False node_copy = copy.deepcopy(node) start, end, arg_lib, arg_client, new_leaf = self.merge_libs_calls(node) if leaf is not None and len(new_leaf) > 0: leaf = leaf.union(new_leaf) if arg_client is not None and arg_lib is not None: node = arg_client hook_installed = True elif (known_child is not None and known_child.raw_lib_node is not None): known_child_content = known_child.raw_lib_node child_parent = self.parent_child.get(known_child_content, None) if child_parent is not None and isinstance(child_parent, c_ast.Compound): index = child_parent.block_items.index(known_child_content) #child_parent = copy.deepcopy(child_parent) child_parent.block_items[index] = c_ast.Compound(block_items=[ c_ast.FuncCall(name=c_ast.ID(name="CLEVER_DELETE"), args=c_ast.ParamList( params=[])), known_child_content ]) hook_installed = True should_remove = True if leaf is None: leaf = set() result = complete_functions(ClientContextDag(copy.deepcopy(node), node_copy, copy.deepcopy(lib_node), parent, raw_lib_node, arg_lib, leaf=leaf), self.client, self.lib_name, is_MLCCheker=is_MLCCheker) if (hook_installed): CUV = CleanUpVisitor() CUV.visit(result.node) if should_remove: child_parent.block_items.pop(index) return result, leaf
def get_valid_input(file_path): generator = c_generator.CGenerator() file_ast = parse_file(file_path, use_cpp=True, cpp_path='gcc', cpp_args=['-E', r'-Iutils/fake_libc_include']) FDH = FunDefHunter() all_func = FDH.getallFunDef(file_ast) #now build a function call graph for func in all_func: func_node = create_tree_node(func) FCH = FuncCallHunter() callees = FCH.getallFunCall(func) for callee_name in callees: callee = retrive_funcdeff_by_name(all_func, callee_name) if callee is not None: func_node.add_child(callee) #roots_list = find_roots() #leaves_list = find_leaves() correction = False #stop until fix point while not correction: correction = True for func_def_node_value in all_func: DUV = DUVisitor() DUV.visit(func_def_node_value) #print (DUV.missing_define) for miss_def in DUV.missing_define: correction = False #add paramters if func_def_node_value.decl.type.args is None: func_def_node_value.decl.type.args = c_ast.ParamList(params=[]) func_def_node_value.decl.type.args.params.append( c_ast.Decl(name=miss_def, quals=[], storage=[], init=None, funcspec=[], bitsize=None, type=c_ast.TypeDecl(declname=miss_def, quals=[], type=c_ast.IdentifierType(['int'])))) #add arguments func_name = func_def_node_value.decl.name invocs = FunctionCallNodes.get(func_name, set()) ID = c_ast.ID(name= miss_def) for invo in invocs: if (isinstance(invo, c_ast.FuncCall)): if invo.args is None: invo.args = c_ast.ExprList(exprs=[]) invo.args.exprs.append(ID) print(generator.visit(file_ast)) return True
def MakePrintfStyleDecl(name: str, type_names: List[str], is_pointer=False): parameter_fd = c_ast.Decl("fd", [], [], [], MakeSimpleTypeDecl("fd", ["int"]), None, None) parameter_value = c_ast.Decl("value", [], [], [], MakeSimpleTypeDecl("value", type_names), None, None) if is_pointer: parameter_value.type = c_ast.PtrDecl([], parameter_value.type) fun_result = MakeSimpleTypeDecl(name, ["int"]) return c_ast.Decl( name, [], [], [], c_ast.FuncDecl(c_ast.ParamList([parameter_fd, parameter_value]), fun_result), None, None)
def createTest(block,functionName,varVals,varTypes): #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 returnStmt=c_ast.Return(c_ast.Constant(type="int",value="0")) comp=c_ast.Compound([returnStmt]) main= c_ast.FuncDef(mainDec,None,comp) insertTest(main,"func",['1','2'],['int','int'])
def visit_FuncDecl(self, node): ty = c_ast.TypeDecl(declname='_hidden', quals=[], type=c_ast.IdentifierType(['int'])) newdecl = c_ast.Decl( name='_hidden', quals=[], storage=[], funcspec=[], type=ty, init=None, bitsize=None, coord=node.coord) if node.args: node.args.params.append(newdecl) else: node.args = c_ast.ParamList(params=[newdecl])
def type_from_global_decl(decl: ca.Decl) -> CType: """Get the CType of a global Decl, stripping names of function parameters.""" tp = decl.type if not isinstance(tp, ca.FuncDecl) or not tp.args: return tp def anonymize_param(param: ca.Decl) -> ca.Typename: param = copy.deepcopy(param) param.name = None set_decl_name(param) return ca.Typename(name=None, quals=param.quals, type=param.type) new_params: List[Union[ca.Decl, ca.ID, ca.Typename, ca.EllipsisParam]] = [ anonymize_param(param) if isinstance(param, ca.Decl) else param for param in tp.args.params ] return ca.FuncDecl(args=ca.ParamList(new_params), type=tp.type)
def make_internal_fn_decl(name): '''str -> c_ast''' # don't you wish python had a macro system? return c_ast.Decl( name, [], [], [], c_ast.FuncDecl( c_ast.ParamList([ c_ast.Decl( utils.args_tag, [], [], [], c_ast.PtrDecl([], c_ast.TypeDecl( utils.args_tag, [], c_ast.IdentifierType([ '%s%s' % (utils.decomp_tag, utils.args_tag) ]))), None, None) ]), c_ast.TypeDecl(name, [], c_ast.IdentifierType(['void']))), None, None)
def fndecl(name, inargs, outargs, code): ptroutargs = [deepcopy(arg) for arg in outargs] rename = RenameVisitor("out") for arg in ptroutargs: rename.visit(arg) arg.type = c_ast.PtrDecl([], arg.type) arg.init = None fdecl = c_ast.FuncDecl( c_ast.ParamList(inargs + ptroutargs), c_ast.TypeDecl(name, [], c_ast.IdentifierType(['void']))) decl = c_ast.Decl(name, [], [], [], fdecl, None, None) assign = [] for ptr, var in zip(ptroutargs, outargs): assign.append( c_ast.Assignment('=', c_ast.UnaryOp('*', c_ast.ID(ptr.name)), c_ast.ID(var.name))) comp = c_ast.Compound(code + assign) return c_ast.FuncDef(decl, None, comp)
def __init__(self, fileName, funcName): self.fileName = fileName self.ast = parse_file(fileName) self.otherFuncs = [] for func in self.ast.ext: if (isinstance(func, c_ast.FuncDef)): if func.decl.name == funcName: self.target = func if (isinstance( func.children()[0][1].children()[0][1].children() [0][1], c_ast.ParamList)): self.params = func.children()[0][1].children( )[0][1].children()[0][1] else: # print("Completing") self.params = c_ast.ParamList([]) self.target.decl.type.args = self.params elif func.decl.name != "main": self.otherFuncs.append(func) else: self.otherFuncs.append(func)
def _get_assume_definition(self): param_name = '__cond' int_type = a.TypeDecl(param_name, [], a.IdentifierType(['int'])) param_list = a.ParamList( [a.Decl(param_name, [], [], [], int_type, None, None)]) assume_type = a.TypeDecl('__VERIFIER_assume', [], a.IdentifierType(['void'])) assume_func_decl = a.FuncDecl(param_list, assume_type) assume_decl = a.Decl('__VERIFIER_assume', list(), list(), list(), assume_func_decl, None, None) exit_code = a.ExprList([a.Constant('int', '0')]) true_branch = a.Compound([a.FuncCall(a.ID('exit'), exit_code)]) false_branch = None if_statement = a.If(a.UnaryOp('!', a.ID(param_name)), true_branch, false_branch) return_statement = a.Return(None) body_items = [if_statement, return_statement] assume_body = a.Compound(body_items) return a.FuncDef(assume_decl, None, assume_body)
def complete_functions(func_object, client_template, lib, is_MLCCheker=True): if not is_MLCCheker: func = func_object.raw_node if not isinstance(func, c_ast.FuncDef): DUV = DUVisitor() DUV.visit(func) new_func = copy.deepcopy(client_template) new_func.decl.name = client_template.decl.name renamed_type = new_func.decl.type template_type = client_template.decl.type while not isinstance(template_type, c_ast.TypeDecl): renamed_type = renamed_type.type template_type = template_type.type renamed_type.declname = template_type.declname new_func.decl.type.args = c_ast.ParamList([]) new_func.body.block_items = [] new_func.body.block_items.append(copy.deepcopy(func)) for missing_def in DUV.missing_define: new_func.decl.type.args.params.append( c_ast.Decl(name=missing_def, quals=[], storage=[], init=None, funcspec=[], bitsize=None, type=c_ast.TypeDecl( declname=missing_def, quals=[], type=c_ast.IdentifierType( get_type(missing_def))))) if missing_def in DUV.value_changed: new_func.body.block_items.append( c_ast.Return(c_ast.ID(missing_def))) else: new_func = func func_object.raw_node = new_func func = func_object.node if not isinstance(func, c_ast.FuncDef): DUV = DUVisitor() DUV.visit(func) new_func = copy.deepcopy(client_template) new_func.decl.name = client_template.decl.name renamed_type = new_func.decl.type template_type = client_template.decl.type while not isinstance(template_type, c_ast.TypeDecl): renamed_type = renamed_type.type template_type = template_type.type renamed_type.declname = template_type.declname new_func.decl.type.args = c_ast.ParamList([]) new_func.body.block_items = [] new_func.body.block_items.append(copy.deepcopy(func)) for missing_def in DUV.missing_define: new_func.decl.type.args.params.append( c_ast.Decl(name=missing_def, quals=[], storage=[], init=None, funcspec=[], bitsize=None, type=c_ast.TypeDecl(declname=missing_def, quals=[], type=c_ast.IdentifierType( ['int'])))) if missing_def in DUV.value_changed: new_func.body.block_items.append( c_ast.Return(c_ast.ID(missing_def))) #if func is a just a program segment, then also add local variables if isinstance(func, c_ast.Compound): for value_changed in DUV.value_changed: if value_changed not in DUV.missing_define: new_func.body.block_items.append( c_ast.Return(c_ast.ID(value_changed))) else: new_func = func func_object.node = checker.version_merge_client(new_func, lib) set_of_define_interest = set() set_of_change_define_interest = set() if func_object.arg_lib is not None and isinstance(func, c_ast.FuncDef): temp_client_func = func_object.node CUV = CleanUpVisitor() CUV.visit(temp_client_func) DUV = DUVisitor() DUV.visit(temp_client_func) for define in DUV.define: set_of_change_define_interest.add(define) for missing_def in DUV.missing_define: set_of_define_interest.add(missing_def) temp_client_func.body.block_items.insert( 0, c_ast.Decl(name=missing_def, quals=[], storage=[], init=None, funcspec=[], bitsize=None, type=c_ast.TypeDecl(declname=missing_def, quals=[], type=c_ast.IdentifierType( get_type(missing_def))))) func_object.node = temp_client_func if func != func_object.lib_node: func = func_object.lib_node if not isinstance(func, c_ast.FuncDef): DUV = DUVisitor() DUV.visit(func) new_func = copy.deepcopy(client_template) new_func.decl.name = client_template.decl.name renamed_type = new_func.decl.type template_type = client_template.decl.type while not isinstance(template_type, c_ast.TypeDecl): renamed_type = renamed_type.type template_type = template_type.type renamed_type.declname = template_type.declname new_func.decl.type.args = c_ast.ParamList([]) new_func.body.block_items = [] new_func.body.block_items.append(copy.deepcopy(func)) for missing_def in DUV.missing_define: new_func.decl.type.args.params.append( c_ast.Decl(name=missing_def, quals=[], storage=[], init=None, funcspec=[], bitsize=None, type=c_ast.TypeDecl( declname=missing_def, quals=[], type=c_ast.IdentifierType( get_type(missing_def))))) if missing_def in DUV.value_changed: new_func.body.block_items.append( c_ast.Return(c_ast.ID(missing_def))) func_object.lib_node = new_func elif func_object.arg_lib is not None: func_object.lib_node = func else: func_object.lib_node = new_func if func_object.arg_lib is not None: func = func_object.arg_lib if not isinstance(func, c_ast.FuncDef): DUV = DUVisitor() DUV.visit(func) new_func = copy.deepcopy(client_template) new_func.decl.name = client_template.decl.name renamed_type = new_func.decl.type template_type = client_template.decl.type while not isinstance(template_type, c_ast.TypeDecl): renamed_type = renamed_type.type template_type = template_type.type renamed_type.declname = template_type.declname new_func.decl.type.args = c_ast.ParamList([]) new_func.body.block_items = [] if isinstance(func, c_ast.Compound): new_func.body.block_items = copy.deepcopy(func).block_items else: new_func.body.block_items.append(copy.deepcopy(func)) for missing_def in DUV.missing_define: new_func.decl.type.args.params.append( c_ast.Decl(name=missing_def, quals=[], storage=[], init=None, funcspec=[], bitsize=None, type=c_ast.TypeDecl( declname=missing_def, quals=[], type=c_ast.IdentifierType( get_type(missing_def))))) if missing_def in DUV.value_changed: new_func.body.block_items.append( c_ast.Return(c_ast.ID(missing_def))) for defintion in DUV.define: if defintion not in DUV.missing_define and ( (defintion + "_old" in set_of_define_interest or defintion + "_new" in set_of_define_interest or defintion in set_of_define_interest) or (defintion in DUV.value_changed and (defintion + "_old" in set_of_change_define_interest) or (defintion + "_new" in set_of_change_define_interest))): new_func.body.block_items.append( c_ast.Return(c_ast.ID(defintion))) func_object.arg_lib = new_func else: func_object.arg_lib = func return func_object
def create_test_harness(path_old, path_new, client, lib): old_ast = parse_file(path_old, use_cpp=True, cpp_path='gcc', cpp_args=['-E', r'-Iutils/fake_libc_include']) new_ast = parse_file(path_new,use_cpp=True, cpp_path='gcc', cpp_args=['-E', r'-Iutils/fake_libc_include']) old_lib_visitor = FuncDefVisitor(lib) old_lib_visitor.visit(old_ast) old_lib_node = old_lib_visitor.container assert not old_lib_node is None, "old lib does not exist" if isinstance(old_lib_node, c_ast.FuncDef): old_lib_node.decl.name += "_old" old_lib_node.decl.type.type.declname += "_old" old_client_visitor = FuncDefVisitor(client) old_client_visitor.visit(old_ast) old_client_node = old_client_visitor.container assert not old_client_node is None, "old lib client not exist" if isinstance(old_lib_node, c_ast.FuncDef): old_client_node.decl.name += "_old" old_client_node.decl.type.type.declname += "_old" new_lib_visitor = FuncDefVisitor(lib) new_lib_visitor.visit(new_ast) new_lib_node = new_lib_visitor.container assert not new_lib_node is None, "new lib does not exist" if isinstance(new_lib_node, c_ast.FuncDef): new_lib_node.decl.name += "_new" new_lib_node.decl.type.type.declname += "_new" new_client_visitor = FuncDefVisitor(client) new_client_visitor.visit(new_ast) new_client_node = new_client_visitor.container assert not new_client_node is None, "new client does not exist" if isinstance(new_client_node, c_ast.FuncDef): new_client_node.decl.name += "_new" new_client_node.decl.type.type.declname += "_new" LHR_new = LibInvoHunter_Reanme(lib, "new") LHR_new.visit(new_client_node) LHR_old = LibInvoHunter_Reanme(lib, "old") LHR_old.visit(old_client_node) #ceate the main function main_func = copy.deepcopy(old_client_node) main_func.decl.name = "CLEVER_main" main_func.decl.type.type.declname ="CLEVER_main" main_func.decl.type.args = c_ast.ParamList(params=[]) main_func.body.block_items =[] calling_list = [] if new_client_node.decl.type.args is not None: for decl in new_client_node.decl.type.args.params: main_func.body.block_items.append(copy.deepcopy(decl)) if not decl.name is None: main_func.body.block_items.append(make_klee_symbolic(decl.name, decl.name)) calling_list.append(c_ast.ID(name=decl.name)) old_client_invo = c_ast.FuncCall(name=c_ast.ID(old_client_node.decl.name), args=c_ast.ExprList(exprs=calling_list)) new_client_invo = c_ast.FuncCall(name=c_ast.ID(new_client_node.decl.name), args=c_ast.ExprList(exprs=calling_list)) format_string = "" ID_list= [] for arg in calling_list: arg_name = arg.name format_string += "CEX {name} : %d,".format(name=arg_name) ID_list.append(c_ast.FuncCall(name=c_ast.ID(name="klee_get_valued"), args=c_ast.ExprList(exprs=[c_ast.ID(name=arg_name)]))) format_string = format_string.rstrip(",") main_func.body.block_items.append(c_ast.FuncCall(name=c_ast.ID(name= "klee_assume"), args=c_ast.BinaryOp(op="!=", left=old_client_invo, right=new_client_invo))) main_func.body.block_items.append(c_ast.FuncCall(name=c_ast.ID(name="printf"), args=c_ast.ExprList(exprs=([c_ast.Constant(type='string', value="\" CLEVER NEQ \\n" + "\"")])))) main_func.body.block_items.append(c_ast.FuncCall(name=c_ast.ID(name="printf"), args=c_ast.ExprList(exprs=([c_ast.Constant(type='string', value="\"" + format_string +"\\n" +"\"")] + ID_list)))) main_func.body.block_items.append(c_ast.FuncCall(name=c_ast.ID(name="abort"), args=c_ast.ExprList(exprs=[]))) harness_File = old_ast harness_File.ext = (harness_File.ext + [new_lib_node ,new_client_node, main_func]) generator = c_generator.CGenerator() output_string = Klee_Header_String + generator.visit(harness_File) output_file_name = "klee_unmerged.c" with open(output_file_name, "w") as outfile: outfile.write(output_string) #print(output_string) return harness_File, output_file_name
if is_pointer: parameter_value.type = c_ast.PtrDecl([], parameter_value.type) fun_result = MakeSimpleTypeDecl(name, ["int"]) return c_ast.Decl( name, [], [], [], c_ast.FuncDecl(c_ast.ParamList([parameter_format, parameter_value]), fun_result), None, None) PUTS = c_ast.Decl( "print", [], [], [], c_ast.FuncDecl( c_ast.ParamList([ c_ast.Decl("s", [], [], [], c_ast.PtrDecl([], MakeSimpleTypeDecl("s", ["char"])), None, None) ]), MakeSimpleTypeDecl("print", ["int"])), None, None) PRINTF_PROTOTYPES = { "printf_u": MakePrintfStyleDecl("printf_u", ["int", "unsigned"]), "printf_d": MakePrintfStyleDecl("printf_d", ["int"]), "printf_lu": MakePrintfStyleDecl("printf_lu", ["long", "long", "unsigned"]), "printf_ld": MakePrintfStyleDecl("printf_ld", ["long", "long"]), "printf_f": MakePrintfStyleDecl("printf_f", ["double"]), "printf_c": MakePrintfStyleDecl("printf_c", ["char"]), "printf_p": MakePrintfStyleDecl("printf_p", ["void"], True), "printf_s": MakePrintfStyleDecl("printf_s", ["char"], True) }
def function_ptr_decl(name, return_type, parameters): return decl( name, node.PtrDecl([], node.FuncDecl(node.ParamList(parameters), return_type)))
def complete_functions(func_object, client_template, lib, vistor, is_MLCCheker=True): if not is_MLCCheker: func = func_object.raw_node if not isinstance(func, c_ast.FuncDef): DUV = DUVisitor() DUV.visit(func) new_func = copy.deepcopy(client_template) new_func.decl.name = client_template.decl.name renamed_type = new_func.decl.type template_type = client_template.decl.type while not isinstance(template_type, c_ast.TypeDecl): renamed_type = renamed_type.type template_type = template_type.type renamed_type.declname = template_type.declname new_func.decl.type.args = c_ast.ParamList([]) new_func.body.block_items = [] new_func.body.block_items.append(copy.deepcopy(func)) for missing_def in DUV.missing_define: def_type = get_def_type(missing_def, func_object, vistor) new_func.decl.type.args.params.append( c_ast.Decl(name=missing_def, quals=[], storage=[], init=None, funcspec=[], bitsize=None, type=def_type)) if missing_def in DUV.value_changed: new_func.body.block_items.append( c_ast.Return(c_ast.ID(missing_def))) else: new_func = func func_object.raw_node = new_func func = func_object.node DUV = DUVisitor() DUV.visit(func) new_func = copy.deepcopy(client_template) new_func.decl.name = client_template.decl.name renamed_type = new_func.decl.type template_type = client_template.decl.type while not isinstance(template_type, c_ast.TypeDecl): renamed_type = renamed_type.type template_type = template_type.type renamed_type.declname = template_type.declname new_func.decl.type.args = c_ast.ParamList([]) new_func.body.block_items = [] if isinstance(func, c_ast.FuncDef): new_func.body = copy.deepcopy(func.body) new_func.decl.type.args = copy.deepcopy(func.decl.type.args) else: new_func.body.block_items.append(copy.deepcopy(func)) return_statement = [] count = 0 for missing_def in DUV.missing_define: def_type = get_def_type(missing_def, func_object, vistor) if def_type is None: continue new_func.decl.type.args.params.append( c_ast.Decl(name=missing_def, quals=[], storage=[], init=None, funcspec=[], bitsize=None, type=def_type)) if missing_def in DUV.value_changed: #return_statement.append(c_ast.Return(c_ast.ID(missing_def))) return_statement.append( c_ast.FuncCall(name=c_ast.ID(name="_RETTYPE"), args=c_ast.ExprList(exprs=[ c_ast.ID(missing_def), c_ast.Constant(type='int', value=str(count)) ]))) count += 1 #if func is a just a program segment, then also add local variables if isinstance(func, c_ast.Compound): for value_changed in DUV.value_changed: if value_changed not in DUV.missing_define: #return_statement.append(c_ast.Return(c_ast.ID(value_changed))) return_statement.append( c_ast.FuncCall( name=c_ast.ID(name="_RETTYPE"), args=c_ast.ExprList(exprs=[ c_ast.ID(value_changed), c_ast.Constant(type='int', value=str(count)) ]))) count += 1 return_statement.append( c_ast.FuncCall(name=c_ast.ID(name="END"), args=None)) JPV = JumpVisitor() JPV.visit_and_work(new_func, return_statement) new_func.body.block_items = new_func.body.block_items + return_statement #func_object.node = checker.version_merge_client(new_func, lib) func_object.node = new_func set_of_define_interest = set() set_of_change_define_interest = set() if func_object.arg_lib is not None and isinstance(func, c_ast.FuncDef): temp_client_func = func_object.node CUV = CleanUpVisitor() CUV.visit(temp_client_func) DUV = DUVisitor() DUV.visit(temp_client_func) for define in DUV.define: set_of_change_define_interest.add(define) for missing_def in DUV.missing_define: def_type = get_def_type(missing_def, func_object, vistor) set_of_define_interest.add(missing_def) temp_client_func.body.block_items.insert( 0, c_ast.Decl(name=missing_def, quals=[], storage=[], init=None, funcspec=[], bitsize=None, type=def_type)) func_object.node = temp_client_func if func != func_object.lib_node: func = func_object.lib_node if not isinstance(func, c_ast.FuncDef): DUV = DUVisitor() DUV.visit(func) new_func = copy.deepcopy(client_template) new_func.decl.name = client_template.decl.name renamed_type = new_func.decl.type template_type = client_template.decl.type while not isinstance(template_type, c_ast.TypeDecl): renamed_type = renamed_type.type template_type = template_type.type renamed_type.declname = template_type.declname new_func.decl.type.args = c_ast.ParamList([]) new_func.body.block_items = [] new_func.body.block_items.append(copy.deepcopy(func)) return_statement = [] for missing_def in DUV.missing_define: def_type = get_def_type(missing_def, func_object, vistor) if def_type is None: continue new_func.decl.type.args.params.append( c_ast.Decl(name=missing_def, quals=[], storage=[], init=None, funcspec=[], bitsize=None, type=def_type)) if missing_def in DUV.value_changed: return_statement.append(c_ast.Return( c_ast.ID(missing_def))) JPV = JumpVisitor() JPV.visit_and_work(new_func, return_statement) new_func.body.block_items = new_func.body.block_items + return_statement func_object.lib_node = new_func elif func_object.arg_lib is not None: func_object.lib_node = func else: func_object.lib_node = new_func if func_object.arg_lib is not None: func = func_object.arg_lib if not isinstance(func, c_ast.FuncDef): DUV = DUVisitor() DUV.visit(func) new_func = copy.deepcopy(client_template) new_func.decl.name = client_template.decl.name renamed_type = new_func.decl.type template_type = client_template.decl.type while not isinstance(template_type, c_ast.TypeDecl): renamed_type = renamed_type.type template_type = template_type.type renamed_type.declname = template_type.declname new_func.decl.type.args = c_ast.ParamList([]) new_func.body.block_items = [] if isinstance(func, c_ast.Compound): new_func.body.block_items = copy.deepcopy(func).block_items else: new_func.body.block_items.append(copy.deepcopy(func)) for missing_def in DUV.missing_define: def_type = get_def_type(missing_def, func_object, vistor) new_func.decl.type.args.params.append( c_ast.Decl(name=missing_def, quals=[], storage=[], init=None, funcspec=[], bitsize=None, type=def_type)) if missing_def in DUV.value_changed: new_func.body.block_items.append( c_ast.Return(c_ast.ID(missing_def))) for defintion in DUV.define: if defintion not in DUV.missing_define and ( (defintion + "_old" in set_of_define_interest or defintion + "_new" in set_of_define_interest or defintion in set_of_define_interest) or (defintion in DUV.value_changed and (defintion + "_old" in set_of_change_define_interest) or (defintion + "_new" in set_of_change_define_interest))): new_func.body.block_items.append( c_ast.Return(c_ast.ID(defintion))) func_object.arg_lib = new_func else: func_object.arg_lib = func return func_object
def __init__(self, function, has_implementation, real_variadic_function, generator): self.function = function self.func_name = function.name self.real_variadic_function = real_variadic_function self.struct_names = generator.struct_names self.struct_typedef_names = generator.struct_typedef_names self.wrapped_func = f'__wrap_{self.func_name}' self.real_func = f'__real_{self.func_name}' self.state_name = f'nala_mock_{self.func_name}' self.generator = generator self.func_decl = self.function.declaration.type self.func_params = self.func_decl.args.params if self.func_decl.args else [] self.assign_names_to_unnamed_params(self.func_params) self.is_variadic_func = False self.params = [] for param in self.func_params: if is_ellipsis(param): self.is_variadic_func = True break if param.name is None: break expanded_param = deepcopy(param) expanded_param.type = self.generator.parser.expand_type( expanded_param.type) self.params.append((param, expanded_param)) if has_implementation is not None: self.has_implementation = has_implementation elif self.is_variadic_func: if real_variadic_function: self.has_implementation = True else: self.has_implementation = False else: self.has_implementation = True self.params_struct = [] for param, expanded_param in self.params: if is_array(expanded_param.type): param = deepcopy(expanded_param) param.type = self.convert_array_to_pointer(param.type) param = self.rename_param(param, param.name) if 'const' in param.type.quals: param = deepcopy(param) param.type.quals = [ qual for qual in param.type.quals if qual != 'const' ] self.params_struct.append(param) self.forward_args = ', '.join(param.name for param in self.params_struct) if self.is_variadic_func: self.params_struct.append( decl( None, c_ast.PtrDecl([], c_ast.TypeDecl( 'vafmt_p', ['const'], c_ast.IdentifierType(['char']))))) self.forward_args += ', nala_vl' # -Wpedantic warns on empty structs. if not self.params_struct: self.params_struct = [ decl( 'dummy', c_ast.TypeDecl('dummy', [], c_ast.IdentifierType(['int']))) ] return_type = self.func_decl.type self.return_value = ( None if isinstance(return_type, c_ast.TypeDecl) and isinstance(return_type.type, c_ast.IdentifierType) and return_type.type.names[0] == 'void' else 'return_value') if self.is_variadic_func: self.va_list_start_arg_name = self.func_params[-2].name else: self.va_list_start_arg_name = None self.return_value_decl = decl( self.return_value, rename_return_type(return_type, self.return_value)) mock_params = self.create_mock_params() self.implementation_decl = function_ptr_decl( 'implementation', rename_return_type(return_type, 'implementation'), create_implementation_params(self.func_params)) self.mock_func = self.void_function_decl(f'{self.func_name}_mock', mock_params) self.mock_once_func = self.int_function_decl( f'{self.func_name}_mock_once', mock_params) self.set_errno_func = self.void_function_decl( f'{self.func_name}_mock_set_errno', [ decl( 'errno_value', c_ast.TypeDecl('errno_value', [], c_ast.IdentifierType(['int'])), ) ]) self.callback_decl = function_ptr_decl( 'callback', void_type('callback'), create_implementation_params(self.func_params)) self.variadic_func_real_wrapper_decl = c_ast.FuncDecl( c_ast.ParamList(create_implementation_params(self.func_params)), c_ast.TypeDecl(f'{self.func_name}_mock_va_arg_real', [], return_type)) self.default_variadic_func_real_wrapper_decl = c_ast.FuncDecl( c_ast.ParamList(create_implementation_params(self.func_params)), c_ast.TypeDecl(f'nala_v{self.func_name}', [], return_type)) self.real_decl = self.rename_function(self.real_func) self.wrapped_decl = self.rename_function(self.wrapped_func) self.instance_members = [] self.set_params = [] self.char_pointer_params = [] self.pointer_params = [] self.non_pointer_params = [] self.ignore_params = [] for param, expanded_param in self.params: if is_struct_or_union(expanded_param.type): continue elif is_va_list(expanded_param.type): continue self.instance_members.append(bool_param(f'ignore_{param.name}_in')) if is_pointer_or_array(expanded_param.type): if is_char_pointer(expanded_param.type): self.char_pointer_params.append(param) self.ignore_params.append((param.name, True)) else: self.pointer_params.append(param) else: self.non_pointer_params.append(param) self.ignore_params.append((param.name, False)) continue param_buf = self.rename_param(param, 'buf_p') param_actual = self.rename_param(param, 'actual_p') param_expected = self.rename_param(param, 'expected_p') param_dst = self.rename_param(param, 'dst_p') param_src = self.rename_param(param, 'src_p') self.instance_members.append(set_member(f'{param.name}_in')) self.instance_members.append( in_assert_member(param.name, param_actual, param_expected)) self.instance_members.append(set_member(f'{param.name}_out')) self.instance_members.append( out_copy_member(param.name, param_dst, param_src)) self.set_params.append( (param, param_buf, param_actual, param_expected, param_dst, param_src, self.find_check_function(param, expanded_param)))
def function_ptr_decl(name, return_type, parameters): return decl( name, c_ast.PtrDecl([], c_ast.FuncDecl(c_ast.ParamList(parameters), return_type)))
def int_function_decl(self, name, parameters): if not parameters: parameters = [void_type('')] return c_ast.FuncDecl(c_ast.ParamList(parameters), int_type(name))
def create_test_harness(path_old, path_new, client, lib, cex, index): old_ast = parse_file(path_old, use_cpp=True, cpp_path='gcc', cpp_args=['-E', r'-Iutils/fake_libc_include']) new_ast = parse_file(path_new, use_cpp=True, cpp_path='gcc', cpp_args=['-E', r'-Iutils/fake_libc_include']) old_lib_visitor = FuncDefVisitor(lib) old_lib_visitor.visit(old_ast) old_lib_node = old_lib_visitor.container assert not old_lib_node is None, "old lib does not exist" if isinstance(old_lib_node, c_ast.FuncDef): old_lib_node.decl.name += "_old" old_lib_node.decl.type.type.declname += "_old" old_client_visitor = FuncDefVisitor(client) old_client_visitor.visit(old_ast) old_client_node = old_client_visitor.container assert not old_client_node is None, "old client not exist" if isinstance(old_client_node, c_ast.FuncDef): old_client_node.decl.name += "_old" old_client_node.decl.type.type.declname += "_old" new_lib_visitor = FuncDefVisitor(lib) new_lib_visitor.visit(new_ast) new_lib_node = new_lib_visitor.container assert not new_lib_node is None, "new lib does not exist" if isinstance(new_lib_node, c_ast.FuncDef): new_lib_node.decl.name += "_new" new_lib_node.decl.type.type.declname += "_new" new_client_visitor = FuncDefVisitor(client) new_client_visitor.visit(new_ast) new_client_node = new_client_visitor.container assert not new_client_node is None, "new client does not exist" if isinstance(new_client_node, c_ast.FuncDef): new_client_node.decl.name += "_new" new_client_node.decl.type.type.declname += "_new" LHR_new = LibInvoHunter_Reanme(lib, "new") LHR_new.visit(new_client_node) LHR_old = LibInvoHunter_Reanme(lib, "old") LHR_old.visit(old_client_node) # ceate the main function main_func = copy.deepcopy(old_client_node) main_func.decl.name = "main" main_func.decl.type.type.declname = "main" main_func.decl.type.args = c_ast.ParamList(params=[]) main_func.body.block_items = [] calling_list = [] if (new_client_node.decl.type.args is not None): assert old_client_node.decl.type.args is not None, "arg mismatch" assert len(new_client_node.decl.type.args.params) == len( old_client_node.decl.type.args.params), "arg mismatch" assert len( new_client_node.decl.type.args.params) == len(cex), "arg mismatch" parser = c_parser.CParser() if new_client_node.decl.type.args is not None: for i in range(len(new_client_node.decl.type.args.params)): decl = new_client_node.decl.type.args.params[i] decl_copy = copy.deepcopy(decl) main_func.body.block_items.append(decl_copy) if not decl.name is None and isinstance(decl, c_ast.Decl): value = cex.get(decl.name, None) decl_copy.init = c_ast.Constant(type=decl.type, value=value) calling_list.append(c_ast.ID(name=decl_copy.name)) old_client_invo = c_ast.FuncCall(name=c_ast.ID(old_client_node.decl.name), args=c_ast.ExprList(exprs=calling_list)) new_client_invo = c_ast.FuncCall(name=c_ast.ID(new_client_node.decl.name), args=c_ast.ExprList(exprs=calling_list)) report_cex = c_ast.FuncCall( name=c_ast.ID(name="printf"), args=c_ast.ExprList(exprs=([ c_ast.Constant(type='string', value="\" CEXs validated \\n" + "\"") ]))) report_non_cex = c_ast.FuncCall( name=c_ast.ID(name="printf"), args=c_ast.ExprList(exprs=([ c_ast.Constant(type='string', value="\" spurious error \\n" + "\"") ]))) cond = c_ast.BinaryOp(op="!=", left=old_client_invo, right=new_client_invo) main_func.body.block_items.append( c_ast.If(cond=cond, iftrue=report_cex, iffalse=report_non_cex)) harness_File = old_ast other_things = [] for item in harness_File.ext: if isinstance(item, c_ast.FuncDef): if (item.decl.name != "main"): other_things.append(item) harness_File.ext = (other_things + [new_lib_node, new_client_node, main_func]) generator = c_generator.CGenerator() output_string = "#include <stdio.h> \n" + generator.visit(harness_File) output_file_name = "validation_unmerged_%s.c" % index with open(output_file_name, "w") as outfile: outfile.write(output_string) # print(output_string) return harness_File, output_file_name