def infer_change(old, new): solver = z3.Optimize() included_features = {} positive_features = {} for feature, value in old.items(): control_included = z3.Bool(f'|{feature} included|') control_positive = z3.Bool(f'|{feature} positive|') input_included = value != '0' input_positive = value == '+' output_included = new[feature] != '0' output_positive = new[feature] == '+' included_features[control_included] = feature positive_features[feature] = control_positive positive_explanations = [] for implying_feature, implying_value in ipa_data.get_implying( feature, '+'): implying_included = z3.Bool(f'|{implying_feature} included|') implying_positive = z3.Bool(f'|{implying_feature} positive|') if implying_value == '+': positive_explanations.append( z3.And(implying_included, implying_positive)) else: positive_explanations.append( z3.And(implying_included, z3.Not(implying_positive))) negative_explanations = [] for implying_feature, implying_value in ipa_data.get_implying( feature, '-'): implying_included = z3.Bool(f'|{implying_feature} included|') implying_positive = z3.Bool(f'|{implying_feature} positive|') if implying_value == '+': positive_explanations.append( z3.And(implying_included, implying_positive)) else: positive_explanations.append( z3.And(implying_included, z3.Not(implying_positive))) if not output_included: solver.add(z3.Not(control_included)) solver.add( z3.If( z3.And(control_included, input_included), z3.And(output_included == control_included, output_positive == control_positive), z3.Implies( z3.And(input_included, output_included), z3.Or( output_positive == input_positive, z3.And(output_positive, z3.Or(*positive_explanations), z3.Not(z3.Or(*negative_explanations))), z3.And(z3.Not(output_positive), z3.Or(*negative_explanations), z3.Not(z3.Or(*positive_explanations))))))) for var in included_features.keys(): solver.add_soft(z3.Not(var)) if solver.check() == z3.sat: rule = {} model = solver.model() for ident, feature in included_features.items(): if model[ident]: positive_feature = positive_features[feature] rule[feature] = '+' if model[positive_feature] else '-' return rule else: print('unsat')
def visitB_term(self, ctx): formula = ctx.getChild(ctx.getChildCount() - 1).accept(self) if ctx.getChildCount() > 1: return z3.Not(formula) return formula
def z3Node(self): return z3.Not(self.sub.z3Node())
def rec(t): if t.is_var(): z3_t = convert_const(t.name, t.T, ctx) if t.T == NatType and t.name not in assms: assms[t.name] = z3_t >= 0 return z3_t elif t.is_forall(): nm = name.get_variant_name(t.arg.var_name, var_names) var_names.append(nm) v = Var(nm, t.arg.var_T) z3_v = convert_const(nm, t.arg.var_T, ctx) return z3.ForAll(z3_v, rec(t.arg.subst_bound(v))) elif t.is_exists(): nm = name.get_variant_name(t.arg.var_name, var_names) var_names.append(nm) v = Var(nm, t.arg.var_T) z3_v = convert_const(nm, t.arg.var_T, ctx) return z3.Exists(z3_v, rec(t.arg.subst_bound(v))) elif t.is_number(): return t.dest_number() elif t.is_implies(): return z3.Implies(rec(t.arg1), rec(t.arg)) elif t.is_equals(): return rec(t.arg1) == rec(t.arg) elif t.is_conj(): return z3.And(rec(t.arg1), rec(t.arg)) if ctx is None else z3.And( rec(t.arg1), rec(t.arg), ctx) elif t.is_disj(): return z3.Or(rec(t.arg1), rec(t.arg)) if ctx is None else z3.Or( rec(t.arg1), rec(t.arg), ctx) elif logic.is_if(t): b, t1, t2 = t.args return z3.If(rec(b), rec(t1), rec(t2), ctx) elif t.is_not(): return z3.Not(rec(t.arg), ctx) elif t.is_plus(): return rec(t.arg1) + rec(t.arg) elif t.is_minus(): m, n = rec(t.arg1), rec(t.arg) if t.arg1.get_type() == NatType: return z3.If(m >= n, m - n, 0, ctx) return m - n elif t.is_uminus(): return -rec(t.arg) elif t.is_times(): return rec(t.arg1) * rec(t.arg) elif t.is_less_eq(): return rec(t.arg1) <= rec(t.arg) elif t.is_less(): return rec(t.arg1) < rec(t.arg) elif t.is_greater_eq(): return rec(t.arg1) >= rec(t.arg) elif t.is_greater(): return rec(t.arg1) > rec(t.arg) elif t.is_divides(): return rec(t.arg1) / rec(t.arg) elif t.is_comb('of_nat', 1): if t.get_type() == RealType: if t.arg.is_var(): if t.arg.name not in to_real: nm = name.get_variant_name("r" + t.arg.name, var_names) var_names.append(nm) to_real[t.arg.name] = nm z3_t = convert_const(nm, RealType, ctx) assms[nm] = z3_t >= 0 return z3_t else: return convert_const(to_real[t.arg.name], RealType, ctx) return z3.ToReal(rec(t.arg)) else: raise Z3Exception("convert: unsupported of_nat " + repr(t)) elif t.is_comb('max', 2): a, b = rec(t.arg1), rec(t.arg) return z3.If(a >= b, a, b, ctx) elif t.is_comb('min', 2): a, b = rec(t.arg1), rec(t.arg) return z3.If(a <= b, a, b, ctx) elif t.is_comb('abs', 1): a = rec(t.arg) return z3.If(a >= 0, a, -a, ctx) elif t.is_comb('member', 2): a, S = rec(t.arg1), rec(t.arg) return S(a) elif t.is_comb(): return rec(t.fun)(rec(t.arg)) elif t.is_const(): if t == true: return z3.BoolVal(True, ctx) elif t == false: return z3.BoolVal(False, ctx) else: raise Z3Exception("convert: unsupported constant " + repr(t)) else: raise Z3Exception("convert: unsupported operation " + repr(t))
def JUMPI(self, gstate, jump_addr, condition): new_gstates = [] active_address = gstate.environment.active_address active_account = gstate.wstate.address_to_account[active_address] mstate = gstate.mstate jump_addr = svm_utils.get_concrete_int(jump_addr) function_entry = False gstate.jump_count += 1 if (gstate.jump_count % 3 == 0 and gstate.jump_count > 20 and not svm_utils.check_wstate_reachable(gstate.wstate, 100)): gstate.halt = True return if gstate.pc_addr_to_depth.setdefault((gstate.mstate.pc, jump_addr), 0) >= 3: gstate.halt = True return increase_depth = True current_contract = active_account.contract line = solidity_utils.offset_to_line(current_contract.src_code, mstate.pc, current_contract.src_map) src_code = current_contract.src_code.split('\n')[line].strip() concrete_cond = False if 'assert' in src_code: increase_depth = False if type(condition) == bool: increase_depth = False else: simplified_cond = z3.simplify(condition) if z3.is_true(simplified_cond) or z3.is_false(simplified_cond): concrete_cond = True increase_depth = False if increase_depth: gstate.pc_addr_to_depth[(mstate.pc, jump_addr)] = gstate.pc_addr_to_depth[(mstate.pc, jump_addr)] + 1 instr_idx = svm_utils.get_instruction_index(gstate.environment.disassembly.instruction_list, jump_addr) if instr_idx is None: raise SVMRuntimeError('JUMP to invalid address') dest_opcode = gstate.environment.disassembly.instruction_list[instr_idx]['opcode'] if dest_opcode != 'JUMPDEST': raise SVMRuntimeError('JUMP to invalid address') condition = z3.BoolVal(condition) if isinstance(condition, bool) else condition condition = (condition == 0) if isinstance(condition, z3.BitVecRef) else condition assert isinstance(condition ,z3.BoolRef), 'Invalid condition types!' if not z3.is_false(z3.simplify(condition)): true_gstate = copy(gstate) true_gstate.mstate.pc = instr_idx true_gstate.wstate.constraints.append(condition) if true_gstate.wstate.trace is None: jump_func_name, jump_func_hash = gstate.environment.extract_func_name_hash(gstate.mstate.pc) if jump_func_name: jump_trace = make_trace(active_account, jump_func_name) logging.debug('Entering function %s', jump_trace) true_gstate.wstate.trace = jump_trace new_gstates.extend(self.execute_gstate(true_gstate)) negated_condition = z3.Not(condition) if not z3.is_false(z3.simplify(negated_condition)): false_gstate = copy(gstate) false_gstate.mstate.pc += 1 false_gstate.wstate.constraints.append(negated_condition) new_gstates.extend(self.execute_gstate(false_gstate)) gstate.halt = True return new_gstates
def get_gadget_constraint(self): A = self.get_output0() == self.binop(self.get_input0(), self.get_param0()) return z3.Not(), None
def pred_to_z3(self, predicate_name, step_index, z3_head_vars): assert predicate_name in self.program.get_idb_predicate_names() z3_bodies = [] z3_body_free_vars = [] # Encode all rule bodies into Z3 for rule in self.program.get_rules_for_predicate(predicate_name): skip_rule = False for literal in rule.get_literals(): if literal.atom.name in self.program.get_recursive_idb_predicate_names( ) and step_index == 1: skip_rule = True if skip_rule: continue substitution = {} for var_index in range(len(z3_head_vars)): substitution[rule.head.get_vars() [var_index]] = z3_head_vars[var_index] z3_body_constraints = [] # Keep track of all free variables in the body (which are existentially quantified later) # Encode all literals that appear in the body for literal in rule.get_literals(): literal_predicate = self.get_predicate(literal.atom.name, step_index) z3_literal_vars = [] for literal_var_index in range(len(literal.get_vars())): literal_var = literal.get_vars()[literal_var_index] if literal_var.wildcard: # e.g. Node(_, ..) z3_fresh_var = self.get_fresh_var( literal_predicate.domain(literal_var_index)) z3_body_free_vars.append(z3_fresh_var) z3_literal_vars.append(z3_fresh_var) elif literal_var in substitution.keys(): z3_literal_vars.append(substitution[literal_var]) else: z3_fresh_var = self.get_fresh_var( literal_predicate.domain(literal_var_index)) substitution[literal_var] = z3_fresh_var z3_body_free_vars.append(z3_fresh_var) z3_literal_vars.append(z3_fresh_var) if literal.atom.name in self.program.get_edb_predicate_names( ) or literal.atom.name in self.program.get_nonrecursive_idb_predicate_names( ): if literal.negated: z3_body_constraints.append( z3.Not(literal_predicate(z3_literal_vars))) else: z3_body_constraints.append( literal_predicate(z3_literal_vars)) else: if step_index > 1: (tmp_free_vars, body_constraint) = self.pred_to_z3( literal.atom.name, step_index - 1, z3_literal_vars) z3_body_free_vars = z3_body_free_vars + tmp_free_vars z3_body_constraints.append(body_constraint) else: z3_body_constraints.append(False) # Encode all comparisons that appear in the body (e.g. cost = cost1 + cost2) for comparison in rule.get_comparisons(): # Assume all variables that appear in comparisons are bound to literals z3_left = substitution[comparison.left] z3_right_terms = [] for right_term in comparison.right.get_terms(): if right_term.is_variable: z3_right_terms.append(substitution[right_term]) elif right_term.is_constant and right_term.type == Constant.INTEGER_CONSTANT: z3_right_terms.append(right_term.value) elif right_term.is_constant and right_term.type == Constant.STRING_CONSTANT: z3_right_terms.append( get_string_const_val(right_term.value)) else: raise NameError('Unknown term: {}'.format(right_term)) if comparison.right.is_atomic: z3_right = z3_right_terms[0] else: if comparison.right.op == '+': z3_right = reduce(lambda x, y: x + y, z3_right_terms) else: raise NameError( 'Add support for arithmetic expressions of type {}' .format(comparison.right.op)) if comparison.op == '<': z3_comparison = z3_left < z3_right elif comparison.op == '=': z3_comparison = z3_left == z3_right elif comparison.op == '!=': z3_comparison = z3_left != z3_right else: raise NameError( 'Add support for comparisons of type {}'.format( comparison.op)) z3_body_constraints.append(z3_comparison) # Get the conjunction of all z3 body constraints if len(z3_body_constraints) == 1: z3_body_constraints_conjunction = z3_body_constraints[0] else: z3_body_constraints_conjunction = z3.And(z3_body_constraints) z3_bodies.append(z3_body_constraints_conjunction) # Construct the Z3 constraint for the current predicate z3_constraint = z3.Or( z3_bodies) if len(z3_bodies) > 1 else z3_bodies[0] return (z3_body_free_vars, z3_constraint)
def send_recv(old, pid, val, inpn, size, infd, outpn, outfd): cond = z3.And( is_pid_valid(pid), old.procs[pid].state == dt.proc_state.PROC_SLEEPING, # inpn is a valid pn and belongs to current is_pn_valid(inpn), old.pages[inpn].owner == old.current, z3.ULE(size, dt.PAGE_SIZE), z3.Implies(is_fd_valid(infd), is_fn_valid(old.procs[old.current].ofile(infd))), # outpn is a valid pn and belongs to current is_pn_valid(outpn), old.pages[outpn].owner == old.current, old.pages[outpn].type == dt.page_type.PAGE_TYPE_FRAME, z3.Implies(is_fd_valid(outfd), z3.Not(is_fn_valid(old.procs[old.current].ofile(outfd)))), # if ipc from is set, it must be set to current z3.Implies(old.procs[pid].ipc_from != 0, old.procs[pid].ipc_from == old.current) ) new = old.copy() new.procs[old.current].ipc_page = outpn new.procs[old.current].ipc_fd = outfd new.procs[pid].ipc_from = old.current new.procs[pid].ipc_val = val # memcpy new.pages.data = lambda pn0, idx0, oldfn=new.pages.data: \ util.If(z3.And(pn0 == old.procs[pid].ipc_page, z3.ULT(idx0, size)), oldfn(inpn, idx0), oldfn(pn0, idx0)) new.procs[pid].ipc_size = size new2 = new.copy() cond2 = z3.And(is_fd_valid(infd), is_fd_valid(new2.procs[pid].ipc_fd)) fn = old.procs[old.current].ofile(infd) fd = old.procs[pid].ipc_fd new2.procs[pid].ofile[fd] = fn # bump proc nr_fds new2.procs[pid].nr_fds[fd] += 1 # bump file refcnt new2.files[fn].refcnt[(pid, fd)] += 1 new3 = util.If(cond2, new2, new) new3.procs[old.current].state = dt.proc_state.PROC_SLEEPING new3.procs[pid].state = dt.proc_state.PROC_RUNNING return cond, util.If(cond, new3, old)
#create space for n variables vars = [None] * n #create n z3 Boolean variables for i in range(0, n): vars[i] = z3.Bool("x" + str(i)) # looking for independent set of size 4 k = 4 # we need all combinations of n-k+1 variables comb = n - k + 1 #instantiate a z3 solver solver = z3.Solver() #crearte an Or clause for each combination of n-k+1 variables for c in itertools.combinations(vars, comb): solver.add(z3.Or(c)) # Add constraints on the edges for (s, e) in edges: solver.add(z3.Or(z3.Not(vars[s]), z3.Not(vars[e]))) if (solver.check() == z3.sat): print("Found and IS of size {}".format(k)) m = solver.model() for d in m.decls(): if (m[d] == True): print(d.name()) else: print("No IS of size {} exits".format(k))
def to_z3(self): z3_constraints = [] for predicate_name in self.program.get_idb_predicate_names(): for step_index in range( self.unroll_limit) + [self.unroll_limit + 1]: predicate = self.get_predicate(predicate_name, step_index + 1) #var_names = [ascii_uppercase[-i-1] for i in range(len(ascii_uppercase))] var_names = ['VAR%d' % i for i in range(2000)] z3_head_vars = [] for var_id in range(predicate.arity()): z3_head_vars.append( z3.Const(var_names.pop(), predicate.domain(var_id))) # Declare the head Z3 predicate (e.g. node(X) == ...) z3_head = predicate(z3_head_vars) z3_bodies = [] # Encode all rule bodies into Z3 for rule in self.program.get_rules_for_predicate( predicate_name): lb_vars_to_z3_vars = {} # Consistently substitute all variables that appear in the head for arg_id in range(len(z3_head_vars)): lb_vars_to_z3_vars[rule.head.get_vars() [arg_id]] = z3_head_vars[arg_id] z3_body_constraints = [] # Keep track of all free variables in the body (which are existentially quantified later) z3_body_free_vars = [] # Encode all literals that appear in the body for literal in rule.get_literals(): literal_predicate = self.get_predicate( literal.atom.name, step_index) z3_body_vars = [] for body_var_index in range(len(literal.get_vars())): body_var = literal.get_vars()[body_var_index] if body_var.wildcard: # e.g. Node(_, ..) z3_fresh_var = z3.Const( var_names.pop(), literal_predicate.domain(body_var_index)) z3_body_free_vars.append(z3_fresh_var) z3_body_vars.append(z3_fresh_var) else: if body_var not in lb_vars_to_z3_vars.keys(): # Declare a fresh variable if it does not appear in the head z3_fresh_var = z3.Const( var_names.pop(), literal_predicate.domain( body_var_index)) z3_body_free_vars.append(z3_fresh_var) lb_vars_to_z3_vars[body_var] = z3_fresh_var z3_body_vars.append( lb_vars_to_z3_vars[body_var]) if literal.atom.name in self.recursive_idb_predicate_names and step_index == 0: z3_body_constraints.append(False) continue if literal.negated: z3_body_constraints.append( z3.Not(literal_predicate(z3_body_vars))) else: z3_body_constraints.append( literal_predicate(z3_body_vars)) # Encode all comparisons that appear in the body (e.g. cost = cost1 + cost2) for comparison in rule.get_comparisons(): # Assume all variables that appear in comparisons are bound to literals z3_left = lb_vars_to_z3_vars[comparison.left] z3_right_terms = [] for right_term in comparison.right.get_terms(): if right_term.is_variable: z3_right_terms.append( lb_vars_to_z3_vars[right_term]) elif right_term.is_constant and right_term.type == Constant.INTEGER_CONSTANT: z3_right_terms.append(right_term.value) elif right_term.is_constant and right_term.type == Constant.NODE_CONSTANT and right_term.value in STRING_TO_NODE.keys( ): z3_right_terms.append( STRING_TO_NODE[right_term.value]) elif right_term.is_constant and right_term.type == Constant.INTERFACE_CONSTANT and right_term.value in STRING_TO_INTERFACE.keys( ): z3_right_terms.append( STRING_TO_INTERFACE[right_term.value]) elif right_term.is_constant and right_term.type == Constant.NETWORK_CONSTANT and right_term.value in STRING_TO_NETWORK.keys( ): z3_right_terms.append( STRING_TO_NETWORK[right_term.value]) elif right_term.is_constant and right_term.type == Constant.STRING_CONSTANT and right_term.value in STRING_TO_BITVAL.keys( ): z3_right_terms.append( STRING_TO_BITVAL[right_term.value]) elif right_term.is_constant and right_term.type == Constant.NODE_CONSTANT and right_term.value not in STRING_TO_NODE.keys( ) + STRING_TO_NETWORK.keys( ) + STRING_TO_INTERFACE.keys( ) + STRING_TO_BITVAL.keys(): z3_right_terms.append( get_string_const_val(right_term.value)) else: raise NameError( 'Unknown term: {}'.format(right_term)) if comparison.right.is_atomic: z3_right = z3_right_terms[0] else: if comparison.right.op == '+': z3_right = reduce(lambda x, y: x + y, z3_right_terms) else: raise NameError( 'Add support for arithmetic expressions of type {}' .format(comparison.right.op)) if comparison.op == '<': z3_comparison = z3_left < z3_right elif comparison.op == '=': z3_comparison = z3_left == z3_right elif comparison.op == '!=': z3_comparison = z3_left != z3_right else: raise NameError( 'Add support for comparisons of type {}'. format(comparison.op)) z3_body_constraints.append(z3_comparison) # Get the conjunction of all z3 body constraints if len(z3_body_constraints) == 1: z3_body_constraints_conjunction = z3_body_constraints[ 0] else: z3_body_constraints_conjunction = z3.And( z3_body_constraints) # Quantify free variables (if any) if len(z3_body_free_vars) == 0: z3_body = z3_body_constraints_conjunction else: z3_body = z3.Exists(z3_body_free_vars, z3_body_constraints_conjunction) z3_bodies.append(z3_body) # Construct the Z3 constraint for the current predicate z3_constraint = z3.ForAll( z3_head_vars, z3_head == z3.Or(z3_bodies)) if len(z3_bodies) > 1 else z3.ForAll( z3_head_vars, predicate(z3_head_vars) == z3_bodies[0]) z3_constraints.append(z3_constraint) if predicate_name in self.nonrecursive_idb_predicate_names: break return z3_constraints
def get_gadget_constraint(self): return z3.Not(self.get_output0() == self.binop( self.get_input0(), self.get_input1())), None
def synthetize_rule(self, rule_num, model): """ Synthetize a rule as close as possible to the trace. Print all the unstatisfiable steps and highlight anomalies. """ self.solver.push() # fix dummy variables for soft in self.soft_constr[rule_num]: if model[soft.literal] == True: self.solver.add(soft.literal) elif model[soft.literal] == False: self.solver.add(z3.Not(soft.literal)) # try to optimize intervals # cerco di trovare i numeri più grandi che soddisfano la regola. interval_cost = z3.Real('interval_cost') cost = [] for j, const in enumerate(self.rules[rule_num].constraints): for k in const.greater_equal: cost.append(self.thresholds[rule_num][j][k]) for k in const.lower_equal: cost.append(-self.thresholds[rule_num][j][k]) total_cost = z3.Sum(cost) self.solver.add(interval_cost == total_cost) self.solver.minimize(interval_cost) # check if SAT or UNSAT print('Check Formulas') result = self.solver.check() # print(result) m = self.solver.model() # remove intervall optimization requirements self.solver.pop() # exit if unsat #in teoria non potrebbe mai essere unsat perchè l'abbiamo già risolto prima, ora abbiamo spostato solo le threshold. #se è unsat mi dovrebbe dare delle prove. (NON guardare i log) if result != z3.sat: print("IMPOSSIBLE TO SATISFY, ):") return # print results self.print_rule_result(rule_num, m) # generate 1000 random points inside the rule rule_points = [] generated_points = 0 #crei dei punti perchè potrei non aver visto tutti i casi strani dalle traccie. while generated_points < 1000: point = [0.0, 0.0, 0.0] point[0] = random.uniform(0.0, 1.0) point[1] = random.uniform(0.0, 1.0 - point[0]) point[2] = 1.0 - point[0] - point[1] satisfy_a_constraint = False for i, constraint in enumerate(self.rules[rule_num].constraints): is_ok = True for c in constraint.lower_equal: threshold = to_real(m[self.thresholds[rule_num][i][c]]) if point[c] > threshold: is_ok = False break if not is_ok: continue for c in constraint.greater_equal: threshold = to_real(m[self.thresholds[rule_num][i][c]]) if point[c] < threshold: is_ok = False break if not is_ok: continue satisfy_a_constraint = True break if satisfy_a_constraint: rule_points.append(point) generated_points += 1 # Hellinger distance of unsatisfiable steps failed_rules_diff_action = [] Hellinger_min = [] failed_step_counter = 0 for num, soft in enumerate(self.soft_constr[rule_num]): if m[soft.literal] == False or not (self.actions_in_runs[soft.run][ soft.step] in self.rules[rule_num].speeds): continue failed_rules_diff_action.append(num) P = [ self.belief_in_runs[soft.run][soft.step][0], self.belief_in_runs[soft.run][soft.step][1], self.belief_in_runs[soft.run][soft.step][2] ] hel_dst = [Hellinger_distance(P, Q) for Q in rule_points] Hellinger_min.append(min(hel_dst)) # print unsatisfiable steps in decreasing order of hellinger distance print('Unsatisfiable steps same action:') #anomaly_positions = [] for soft, hel in [[ self.soft_constr[rule_num][x], h ] for h, x in sorted(zip(Hellinger_min, failed_rules_diff_action), key=lambda pair: pair[0], reverse=True)]: print("({})".format(failed_step_counter), end='') if hel > self.threshold: print('ANOMALY: ', end='') print( 'run {} step {}: action {} with belief P_0 = {:.3f} P_1 = {:.3f} P_2 = {:.3f} --- Hellinger = {}' .format(self.run_folders[soft.run], soft.step, self.actions_in_runs[soft.run][soft.step], self.belief_in_runs[soft.run][soft.step][0], self.belief_in_runs[soft.run][soft.step][1], self.belief_in_runs[soft.run][soft.step][2], hel)) failed_step_counter += 1 # if hel > self.threshold: # anomaly_positions.append(pos) failed_steps_same_action = [] for num, soft in enumerate(self.soft_constr[rule_num]): if m[soft.literal] == False or ( self.actions_in_runs[soft.run][soft.step] in self.rules[rule_num].speeds): continue failed_steps_same_action.append(soft) # print unsatisfiable steps in decreasing order of hellinger distance if len(failed_steps_same_action) > 0: print('Unsatisfiable steps different action:') #anomaly_positions = [] for soft in failed_steps_same_action: print( '({}) run {} step {}: action {} with belief P_0 = {:.3f} P_1 = {:.3f} P_2 = {:.3f}' .format(failed_step_counter, self.run_folders[soft.run], soft.step, self.actions_in_runs[soft.run][soft.step], self.belief_in_runs[soft.run][soft.step][0], self.belief_in_runs[soft.run][soft.step][1], self.belief_in_runs[soft.run][soft.step][2])) failed_step_counter += 1
def find_max_satisfiable_rule(self, rule_num): """ Build a model that satisfies as many soft clauses as possible using MAX-SMT """ print('Find maximum number of satisfiable step in rule {}'.format( rule_num)) rule = self.rules[rule_num] # enforce probability axioms for c in range(len(rule.constraints)): # constraint in rule self.thresholds[rule_num].append([None, None, None]) for s in range(3): # state in constraint # TODO 1: questo va tolto e spostato/generalizzato fuori t = z3.Real('t_r{}_c{}_state{}'.format(rule_num, c, s)) self.thresholds[rule_num][c][s] = t # each threshold is a probability and must have a value # bethween 0 and 1 self.solver.add(0.0 < t) self.solver.add(t <= 1.0) # the sum of the probability on the three states must be 1 prob_sum = z3.Sum(self.thresholds[rule_num][c]) self.solver.add(prob_sum == 1.0) # hard constraint, they must be be specified by hand in this version # e.g: x_1 >= 0.9 # TODO 3: usare le variabili dichiarate per esprimere hard-constraint # e.g. rs.add_hard_constraint(x >= 0.7) # TODO 4: rimuovere codice specifico del problema di velocity regulation come la stampa, generazione di punti ecc if rule_num == 0: self.solver.add(self.thresholds[0][0][0] >= 0.70) if rule_num == 1: self.solver.add(self.thresholds[1][0][2] >= 0.70) # build soft clauses for run in range(len(self.belief_in_runs)): t = self.thresholds[rule_num] for bel, belief in enumerate(self.belief_in_runs[run]): # generate boolean var for soft constraints soft = z3.Bool('b_{}_{}_{}'.format(rule_num, run, bel)) self.soft_constr[rule_num].append( DummyVar(soft, rule_num, run, bel)) # add the rule subrules = [] for c in range(len(rule.constraints)): subrule = [] for i in rule.constraints[c].greater_equal: subrule.append( belief[i] >= t[c][i] ) #100 > x1 (esempio) ogni belief è preso da uno step, x1 deve essere soddisfatta per tutti gli step for i in rule.constraints[c].lower_equal: subrule.append(belief[i] <= t[c][i]) subrules.append(z3.And(subrule)) formula = z3.Or( subrules) #ho più modi per soddisfare queste regole. #la mia regola deve spiegare se ha fatto l'azione, altrimenti non deve spiegarla. if self.actions_in_runs[run][ bel] not in rule.speeds: #vedo se l'azione scelta viene rispettata dal bielef formula = z3.Not(formula) self.solver.add( z3.Or(soft, formula) ) #può essere risolto dall cheat (soft) oppure dalla formula. # solve MAX-SMT problem low_threshold = 0 total_soft_constr = len(self.soft_constr[rule_num]) high_threshold = len(self.soft_constr[rule_num]) final_threshold = -1 best_model = [] #uso una ricerca binaria per risolvere l'or gigante definito sopra! while low_threshold <= high_threshold: self.solver.push( ) #risolutore incrementale, consente di evitare di rifare calcoli creando un ambiente virtuale threshold = (low_threshold + high_threshold) // 2 #Pble pseudo boolean less equal self.solver.add( z3.PbLe([(soft.literal, 1) for soft in self.soft_constr[rule_num]], threshold) ) #l'add viene fatto sull'ambiente virtuale appena creato. result = self.solver.check() if result == z3.sat: final_threshold = threshold best_model = self.solver.model() high_threshold = threshold - 1 else: low_threshold = threshold + 1 self.solver.pop() print('fail to satisfy {} steps out of {}'.format( final_threshold, total_soft_constr)) # return a model that satisfy all the hard clauses and the maximum number of soft clauses # print(best_model) return best_model
def _assert(self, modelset, i, g, a): return z3.Not(self.pred._assert(modelset, i, g, a))
def get_gadget_constraint(self): A = self.get_stack_offset() > self.arch.bytes B = self.get_ip_in_stack_offset() == self.arch.bytes return z3.Not(z3.And(A, B)), None
def test_smt(): # fac 0 = 1. # fac {N + 1} = P <== {N >= 0}, {(N + 1) * M = P}, fac N = M. go = lambda t: lambda log, solver: disj( unify(t, arr(lit('fac'), SMT(0), lit('='), SMT(1))), (lambda n, m, p: conj( unify(t, arr(lit('fac'), SMT(n.a + 1), lit('='), p)), add(n.a >= 0), add((n.a + 1) * m.a == p.a), go(arr(lit('fac'), n, lit('='), m)), ))(SMT(z3.Int(nab())), SMT(z3.Int(nab())), SMT(z3.Int(nab()))))(log, solver) # fac 100! X # ---------- # {X = 100!} x = SMT(z3.Int('x')) log = [] solver = z3.Solver() for _ in go(arr(lit('fac'), SMT(100), lit('='), x))(log, solver): print( solver, solver.check(), 'x =', (solver.model()[x.a] if solver.check() == z3.sat else None), ) print(solver) print() # fac X 720 # --------- # X = 7 x = SMT(z3.Int('x')) log = [] solver = z3.Solver() for _ in go(arr(lit('fac'), x, lit('='), SMT(720 * 7)))(log, solver): print( solver, solver.check(), 'x =', (solver.model()[x.a] if solver.check() == z3.sat else None), ) print(solver) print() # enumerating all solutions to constraints # pythag A B C N <== # {0 < A}, {A <= B}, {B <= C}, {C <= N} # {A^2 + B^2 = C^2}. go = lambda t: lambda log, solver: (lambda a, b, c, n: conj( unify(t, arr(lit('pythag'), a, b, c, n)), add(0 < a.a, a.a <= b.a, b.a <= c.a, c.a <= n.a, a.a**2 + b.a**2 == c.a **2))(log, solver))(SMT(z3.Int(nab())), SMT(z3.Int(nab())), SMT(z3.Int(nab())), SMT(z3.Int(nab()))) a = SMT(z3.Int('a')) b = SMT(z3.Int('b')) c = SMT(z3.Int('c')) log = [] solver = z3.Solver() for _ in go(arr(lit('pythag'), a, b, c, SMT(30)))(log, solver): solver.push() while solver.check() == z3.sat: m = solver.model() ma, mb, mc = m[a.a], m[b.a], m[c.a] print(f'a = {ma}, b = {mb}, c = {mc}') solver.add(z3.Not(z3.And(a.a == ma, b.a == mb, c.a == mc))) solver.pop() print() # cbrt {N * N * N} = N. go = lambda t: (lambda n: conj( unify(t, arr(lit('cbrt'), SMT(n.a * n.a * n.a), lit('='), n))))(SMT( z3.Int(nab()))) n = SMT(z3.Int('n')) log = [] solver = z3.Solver() for _ in go(arr(lit('cbrt'), SMT(2019 * 2019 * 2019), lit('='), n))(log, solver): solver.push() while solver.check() == z3.sat: m = solver.model() mn = m[n.a] print(f'n = {mn}') solver.add(n.a != mn) solver.pop() print()
def get_gadget_constraint(self): A = self.get_output0() == self.get_param0() return z3.Not(A), None
def z3expr(self) -> z3.BoolRef: z3expr = self.expr.z3expr() if isinstance(z3expr, z3.BoolRef): return z3.Not(z3expr) raise TypeError
def get_gadget_constraint(self): mem_value = utils.z3_get_memory(self.get_mem_before(), self.get_input0() + self.get_param0(), self.arch.bits, self.arch) A = self.get_output0() == self.binop(mem_value, self.get_input1()) return z3.Not(A), None
def __k_not_bool__(self): for val in self.__k_bool__(): yield inference.InferenceResult(Z3Proxy.init_expr( z3.Not(val.strip_inference_result()), self.defaults), status=True)
def __ne__(self, o): r = self == o if r is NotImplemented: return NotImplemented return wrap(z3.Not(unwrap(r)))
def learn_certain_not_impostor(self, colour): """ learn that the player with the specified colour is certainly not an impostor """ p = self.pid(colour) self.knowns.append(z3.Not(self.impostor[p]))
# ### The CFG with Path Taken if __name__ == "__main__": print('\n### The CFG with Path Taken') if __name__ == "__main__": show_cfg(check_triangle, arcs=cov.arcs()) if __name__ == "__main__": z3.solve(a == b, a == c, z3.Not(b == c)) if __name__ == "__main__": z3.solve(a == b, z3.Not(a == c)) if __name__ == "__main__": with ArcCoverage() as cov: assert check_triangle(1, 1, 0) == 'Isosceles' [i for fn, i in cov._trace if fn == 'check_triangle'] if __name__ == "__main__": paths['<path 3>']
def _ddosSendRules(self): p_0 = z3.Const('%s_dpi_send_p_0'%(self.node), self.ctx.packet) n_0 = z3.Const('%s_dpi_send_n_0'%(self.node), self.ctx.node) t_0 = z3.Int('%s_dpi_send_t_0'%(self.node)) self.constraints.append(z3.ForAll([n_0, p_0, t_0], z3.Not(self.ctx.send(self.node, n_0, p_0, t_0))))
def solve(self): # The way it works is, each box is represented by four symbolic integers, # representing the X/Y coordinates of its top-left and bottom-right vertices. # (Note, however, that because computers are silly, the Y coordinates DECREASE # as you go UP the tower. Just something to keep in mind. Otherwise we get # upside-down stalactite-towers.) svs = {} solver = z3.Solver() for node in self.get_nodes(): svs[node] = ((z3.Int(node + '_x0'), z3.Int(node + '_y0')), (z3.Int(node + '_x1'), z3.Int(node + '_y1'))) # Almost immediately, we need to make some sanity assertions. We want the # top-left corner to actually be "to the left" and "on top of" the bottom-right # corner, so we have to tell the solver that. solver.add(svs[node][0][0] < svs[node][1][0]) solver.add(svs[node][0][1] < svs[node][1][1]) # There's also a bit of logic here to automatically make boxes taller if they # have a lot of text, so that text doesn't overflow awkwardly. This is janky, # but it works! solver.add( svs[node][1][1] - svs[node][0][1] >=\ (len(self.text[node].split('\\')) - len(self.text[node].split('\\')) / 2) ) # And finally, we enforce that everything happens in the first quadrant. solver.add(svs[node][0][0] >= 0) # Now we can put root (recall, the "ground") literally on the ground! solver.add(svs[dag.ROOT][0][0] == 0) solver.add(svs[dag.ROOT][0][1] == 0) # Up next, we enforce that no boxes intersect. This is done by checking if the # X and Y ranges are disjoint (at least one needs to be -- but not necessarily # both!). def ranges_disjoint(x0min, x0max, x1min, x1max): return z3.Or(x0min >= x1max, x0max <= x1min) for node1 in self.get_nodes(): for node2 in self.get_nodes(): if node1 != node2: solver.add( z3.Or( ranges_disjoint(svs[node1][0][0], svs[node1][1][0], svs[node2][0][0], svs[node2][1][0]), ranges_disjoint(svs[node1][0][1], svs[node1][1][1], svs[node2][0][1], svs[node2][1][1]))) # This is the hard one: for each pair of nodes, it creates an "A is on top of # B" assertion, and then asserts either it or its negation, depending on # whether or not B is a direct dependency of A. for node in self.get_nodes(): for dep in self.get_nodes(): on_top = z3.And( # When is "A" on top of "B"? There are two conditions: # First, A's box's floor is directly on B's box's ceiling. svs[node][1][1] == svs[dep][0][1], # Second, the boxes have intersecting X ranges. z3.Not( ranges_disjoint(svs[node][0][0], svs[node][1][0], svs[dep][0][0], svs[dep][1][0]))) if self.is_direct_dependency(node, dep): solver.add(on_top) else: solver.add(z3.Not(on_top)) # Finally, for the sake of ~aesthetics~, there's a bit of logic to # automatically minimize the total perimeter of all the blocks. (Why not area, # you ask? Because area is nonlinear and the solver takes *much* longer to work # with such constrants!) def perimeter(node): return (svs[node][1][0] - svs[node][0][0]) + (svs[node][1][1] - svs[node][0][1]) total_perim = sum([perimeter(node) for node in self.get_nodes()]) # (That's what the loop is for: it keeps asking the solver to "do better" until # the solver can't do any better and gives up. It may or may not be a metaphor # for life.) rects = None perim_tgt = len(self.get_nodes()) * 4 * 3 while True: perim_tgt -= 1 solver.add(total_perim < perim_tgt) check = solver.check() if check == z3.sat: model = solver.model() rects = [] # I translate the solver output into SVG coordinates using some hardcoded # scaling factors and randomized fudge factors. for node in self.get_nodes(): x0 = model.eval(svs[node][0][0]) y0 = model.eval(svs[node][0][1]) x1 = model.eval(svs[node][1][0]) y1 = model.eval(svs[node][1][1]) import random x0 = int(str(x0)) * 160 + 10 + random.choice(range(10)) y0 = int(str(y0)) * 50 x1 = int(str(x1)) * 160 - 10 + random.choice(range(10)) y1 = int(str(y1)) * 50 rects.append((node, x0, y0, x1, y1)) # This is the "solver gives up" case else: return rects
def get_gadget_constraint(self): A = self.get_output0() == self.get_input0() B = self.get_output0() == self.arch.ip return z3.Not(z3.And(A, B)), None
else: s.add(z3.Implies(line[l], connected(a, b))) s.add(z3.Implies(z3.Not(line[l]), z3.Not(connected(a, b)))) # Transitive closure of "is connected to" path_connected = z3.TransitiveClosure(connected) # For every point, if it's activated then it's transitively connected to a point adjacent to a 3-cell xy3 = [xy for (xy, c) in grid.cells() if c == "3"][0] dot3 = grid.cell_dots(*xy3)[0] atom3 = dot_atom[dot3] for d in grid.dots(): s.add(z3.Implies(dot[d], path_connected(dot_atom[d], atom3))) s.add( z3.Implies(z3.Not(dot[d]), z3.Not(path_connected(dot_atom[d], atom3)))) # Constrain the number of activated lines surrounding each known cell def line_count_of_cell(xy): """xy is the dot at the top-left Return an invocation of line_count for the lines around it. """ return z3.Sum(*(bool_to_int(line[l]) for l in grid.cell_lines(*xy))) for xy, c in grid.cells(): if c != " ": print("adding constraint for ", xy, c, [str(l) for l in grid.cell_lines(*xy)]) s.add(line_count_of_cell(xy) == int(c))
def get_gadget_constraint(self): regconstrait = z3.Not( self.get_output0() != self.arch.registers['sp'][0]) offsetconstraint = z3.Not(self.get_param0() < self.arch.bytes * 8) return z3.Or(regconstrait, offsetconstraint), None
def is_true(cond): # NOTE: This differs from `not is_false(cond)`, which corresponds to "may be true" return is_false(z3.Not(cond))
def query_z3(triples_changed): shared = shared_features( [triple for triple, changed in triples_changed if changed]) idents_to_features = { to_ident(feature, position): (feature, position) for feature, position in shared.keys() } opt = z3.Optimize() solver = z3.Solver() solver.set(unsat_core=True) formulas = {} soft_assertions = [] position_weights = {'left': 1000, 'center': 0, 'right': 1000} for control_included, (feature, position) in idents_to_features.items(): # We use 10000 so that including new features is much worse than using more specific features. weight = 10000 + position_weights[position] + ipa_data.get_weight( feature, shared[(feature, position)]) opt.add_soft(z3.Not(z3.Bool(control_included)), weight=weight) for triple, changed in triples_changed: conjunction = [] for i, phone in enumerate(triple): for feature in ipa_data.FEATURES: position = POSITIONS[i] if (feature, position) in shared: control_included = z3.Bool(to_ident(feature, position)) control_positive = shared[(feature, position)] == '+' input_included = phone[ feature] != '0' if feature in phone else False input_positive = phone[ feature] == '+' if feature in phone else False conjunction.append( z3.Implies( control_included, z3.And(input_included, control_positive == input_positive))) formula = z3.And(*conjunction) == changed opt.assert_exprs(formula) name = z3.Bool(get_ident()) formulas[name] = (formula, triple, changed) solver.assert_and_track(formula, name) if opt.check() == z3.sat: rule = ({}, {}, {}) model = opt.model() for ident in model: if model[ident]: feature, position = idents_to_features[str(ident)] rule[POSITIONS.index(position)][feature] = shared[(feature, position)] return rule else: solver.check() unsat_core = solver.unsat_core() print('Unsat core:') for name in unsat_core: formula, (l, c, r), changed = formulas[name] print('Formula:') print(formula) print('Left:') print(ipa_data.FEATURES_TO_SYMBOLS.get(frozenset(l.items()), l)) print('Center:') print(ipa_data.FEATURES_TO_SYMBOLS.get(frozenset(c.items()), c)) print('Right:') print(ipa_data.FEATURES_TO_SYMBOLS.get(frozenset(r.items()), r)) print('Changed:') print(changed) print(formulas[name]) print('Shared:') print(shared) return None