def visit_AsgnStmt(self, node, *args, **kwargs): exp = self.visit(node.rhs, *args, **kwargs) name = node.lhs.name st = kwargs['state'] st.env[name] = z3.FreshInt(name) st.add_pc(st.env[name] == exp) return [st]
def visit_AsgnStmt(self, node, *args, **kwargs): val = self.visit(node.rhs, *args, **kwargs) st = kwargs["state"] name = node.lhs.name sym_val = z3.FreshInt(name) st.env[name] = sym_val st.add_pc(sym_val == val) return st
def visit_WhileStmt_inv (self, node, *args, **kwargs): """" Symbolic execution of while loops with invariants """ print("node.inv=",node.inv) # evaluate invariant before the loop inv_pre = self.visit (node.inv, *args, **kwargs) print("node.inv_2.0=",inv_pre) # fork symbolic state to evaluate the invariant in the pre-condition pre_st, loop_st = kwargs['state'].fork () # pre_st.add_pc (z3.Not (inv_pre)) # if not pre_st.is_empty (): pre_st.add_pc (inv_pre) if pre_st.is_empty (): print ('Invariant not true on loop entry') print (node.inv) print (pre_st) # havoc all variables modified by the loop for v in self._defs (node.body): loop_st.env [v.name] = z3.FreshInt (v.name) # print("v",v,loop_st) # evaluate invariant after havoc and assume it inv_pre = z3.simplify (self.visit (node.inv, *args, state=loop_st)) loop_st.add_pc (inv_pre) # evaluate loop condition cond_val = self.visit (node.cond, *args, state=loop_st); # one state enters the loop, one exits enter_st, exit_st = loop_st.fork () # if enter loop, loop condition is true enter_st.add_pc (cond_val) # if exit loop, loop condition is false exit_st.add_pc (z3.Not (cond_val)) # if loop condition can be satisfied, check invariant preserved by loop body if not enter_st.is_empty (): # do loop body, might produce many new states # print("------------",kwargs["state"],enter_st) for out in self.visit (node.body, *args, state=enter_st): # print("--------------",out) # check that invariant holds at the end of each body inv_post = z3.simplify (self.visit (node.inv, *args, state=out)) # inv_post =self.visit (node.inv, *args, state=out) out.add_pc (z3.Not (inv_post)) if not out.is_empty (): print ('Invariant does not hold on loop exit') print( "2",exit_st) # print ('inv:', node.inv) # print ('inv_post', inv_post) # print ('out', out) # print ('pc', z3.And (out.path).sexpr ()) # if negation of loop condition is satisfied, continue execution after the loop if not exit_st.is_empty (): yield exit_st
def visit_WhileStmt(self, node, *args, **kwargs): if node.inv is not None: pre_inv = z3.simplify(self.visit(node.inv, *args, **kwargs)) p_st, loop_st = kwargs['state'].fork() p_st.add_pc(z3.Not(pre_inv)) if not p_st.is_empty(): print('Invariant is false before entry the loop') print(node.inv) print(p_st) checker = wlang.undef_visitor.UndefVisitor() checker.check(node.body) for v in checker.get_defs(): loop_st.env[v.name] = z3.FreshInt(v.name) inv_pre = z3.simplify(self.visit(node.inv, *args, state=loop_st)) loop_st.add_pc(inv_pre) #if else cond = self.visit(node.cond, *args, state=loop_st) st = loop_st.fork() st[0].add_pc(cond) st[1].add_pc(z3.Not(cond)) #enter loop if not st[0].is_empty(): result = self.visit(node.body, state=st[0]) for out in result: inv_post = z3.simplify( self.visit(node.inv, *args, state=out)) out.add_pc(z3.Not(inv_post)) if not out.is_empty(): print('Invariant violation on loop exit') print('inv:', node.inv) print('out', out) print('pc', z3.And(out.path).sexpr()) if not st[1].is_empty(): return [st[1]] else: return [] todo = [kwargs['state']] done = [] for _ in range(11): if not todo: break res = [] for i in todo: cond = self.visit(node.cond, state=i) st = i.fork() st[0].add_pc(cond) st[1].add_pc(z3.Not(cond)) if not st[0].is_empty(): res.extend(self.visit(node.body, state=st[0])) if not st[1].is_empty(): done.append(st[1]) todo = res return done
def visit_WhileStmt(self, node, *args, **kwargs): # print ("In visit_WhileStmt------------------------------------------",self.While_Output) #no invariant branch if node.inv is None: cond = self.visit(node.cond, *args, **kwargs) IN, NOIN = kwargs["state"].fork() IN.add_pc(cond) NOIN.add_pc(z3.Not(cond)) # print ("What's in IN?",IN,cond) if not IN.is_empty() and self.count <= 10: self.count = self.count + 1 st = self.visit(node.body, *args, **kwargs) kwargs["state"] = st stt = self.visit(node, *args, **kwargs) # self.While_Output.append(kwargs["state"]) elif self.count > 10: self.While_Output = [] return self.While_Output if not NOIN.is_empty(): # self.While_Output=[] self.While_Output.append(NOIN) return self.While_Output else: inv = self.visit(node.inv, *args, **kwargs) first_check, check_over = kwargs["state"].fork() first_check.add_pc(inv) # 1 assert inv; if first_check.is_empty(): print("invariant cannot be hold on entry") return first_check else: # 2 havoc V; for var in self.havoc(node.body): check_over.env[var.name] = z3.FreshInt(var.name) kwargs["state"] = check_over # 3 assume inv; inv = self.visit(node.inv, *args, **kwargs) check_over.add_pc(inv) cond = self.visit(node.cond, *args, **kwargs) # 4 if b then { s ; assert inv; assume false } IN, NOIN = check_over.fork() IN.add_pc(cond) NOIN.add_pc(z3.Not(cond)) if not IN.is_empty(): st = self.visit(node.body, *args, **kwargs) kwargs["state"] = st check_inv = self.visit(node.inv, *args, **kwargs) st.add_pc(z3.Not(check_inv)) if not st.is_empty(): print( "invariant cannot be hold at the end of the loop") if not NOIN.is_empty(): return NOIN
def visit_WhileStmt(self, node, *args, **kwargs): if node.inv is not None: sim_inv = z3.simplify(self.visit(node.inv, *args, **kwargs)) init_state = kwargs['state'].fork() not_inv_state = init_state[0] inv_state = init_state[1] # inv fails initiation if not_inv_state.addcond_isSolvable(z3.Not(sim_inv)): print("inv fails initiation") # use Undefined Use Visitor to find all variables that are modified or defined for var in self._defs(node.body): inv_state.env[var.name] = z3.FreshInt(var.name) # add inv into pc of inv_state inv_state.add_pc(z3.simplify(self.visit(node.inv, *args, state=inv_state))) # fork the state based on the condition and process both conditions accordingly cond = self.visit(node.cond, *args, state=inv_state) inv_states = inv_state.fork() #cond is satisfied, enter the loop if inv_states[0].addcond_isSolvable(cond): final_state = self.visit(node.body, state=inv_states[0]) for st in final_state: if st.addcond_isSolvable(z3.simplify(self.visit(node.inv, *args, state=st))): print("inv fails invariance") if inv_states[1].addcond_isSolvable(z3.Not(cond)): return[inv_states[1]] else: return[] done = [] while_states = [kwargs['state']] executed_time = 1 while(len(while_states) != 0 and executed_time <= 10): executed_time += 1 updated_while_states = [] for state in while_states: cond = self.visit(node.cond, state=state) cond_fork = state.fork() # if after adding condition, state is still solvable, visit node.body, # and extend returned state-list if cond_fork[0].addcond_isSolvable(cond): updated_while_states.extend(self.visit(node.body, state=cond_fork[0])) # if after adding not condition, state is still solvable, append the termination state into returning states if cond_fork[1].addcond_isSolvable(z3.Not(cond)): done.append(cond_fork[1]) while_states = updated_while_states return done
def visit_HavocStmt(self, node, *args, **kwargs): # print ("[sym]In visit_HavocStmt") st = kwargs["state"] for v in node.vars: st.env[v.name] = z3.FreshInt(v.name) return st
def visit_HavocStmt(self, node, *args, **kwargs): st = kwargs['state'] for v in node.vars: st.env[v.name] = z3.FreshInt(v.name) yield st
def visit_HavocStmt(self, node, *args, **kwargs): st = kwargs['state'] for var in node.vars: st.env[var.name] = z3.FreshInt(var.name) return [st]
def visit_WhileStmt(self, node, *args, **kwargs): if node.inv is not None: pre_inv = z3.simplify(self.visit(node.inv, *args, **kwargs)) pre_state, loop_state = kwargs['state'].fork() pre_state.add_pc(z3.Not(pre_inv)) if not pre_state.is_empty(): print("Invariant does not hold before initial loop entry") print(node.inv) print(pre_state) pre_state.mk_error() get_def = wlang.undef_visitor.UndefVisitor() get_def.check(node.body) for var in get_def.get_defs(): loop_state.env[var.name] = z3.FreshInt(var.name) inv_pre = z3.simplify(self.visit(node.inv, *args, state=loop_state)) loop_state.add_pc(inv_pre) cond = self.visit(node.cond, *args, state=loop_state) enter_st, exit_st = loop_state.fork() if not enter_st.is_empty(): res = self.visit(node.body, state=enter_st) for i in res: inv_post = z3.simplify(self.visit(node.inv, *args, state=i)) i.add_pc(z3.Not(inv_post)) if not i.is_empty(): print("Invariant does not hold within the loop") print("inv: ", node.inv) print("inv_post: ", inv_post) print("i: ", i) print("pc", z3.And(i.path).sexpr()) i.mk_error() if not exit_st.is_empty(): return [exit_st] out = [] count = 1 execution = [kwargs['state']] while count <= 10: res = [] for x in execution: cond = self.visit(node.cond, state=x) true_case, false_case = x.fork() true_case.add_pc(cond) false_case.add_pc(z3.Not(cond)) if not false_case.is_empty(): out.append(false_case) if not true_case.is_empty(): kwargs['state'] = self.visit(node.body, state=true_case) res.extend(kwargs['state']) execution = res count += 1 return out
def visit_AsgnStmt(self, node, *args, **kwargs): st = kwargs['state'] x = self.visit(node.rhs, *args, **kwargs) st.env[node.lhs.name] = z3.FreshInt(node.lhs.name) st.add_pc(st.env[node.lhs.name] == x) return [st]