def get_vars_non_recursive(f, include_select=False, include_indices=True): todo = [f] rs = set() seen = set() while todo: expr = todo.pop() if expr.get_id() in seen: continue seen.add(expr.get_id()) if include_select and expr.decl().kind() == z3.Z3_OP_SELECT: arr, idx = expr.children() if z3.is_const(arr): if not include_indices or z3.z3util.is_expr_val(idx): rs.add(expr) else: rs.add(expr) todo.append(idx) else: todo.extend(expr.children()) elif z3.is_const(expr): if not z3.z3util.is_expr_val(expr): rs.add(expr) else: todo.extend(expr.children()) return rs
def get_vars(f, rs=set()): """ shameless copy of z3util.get_vars, but returning select-operations as well. E.g. >>> x = z3.Array('x', z3.IntSort(), z3.IntSort()) >>> get_vars(x[5]) [x[5]] whereas >>> x = z3.Array('x', z3.IntSort(), z3.IntSort()) >>> z3util.get_vars(x[5]) [x] """ if not rs: f = z3.simplify(f) if f.decl().kind() == z3.Z3_OP_SELECT: arr, idx = f.children() if z3.is_const(arr): if z3.z3util.is_expr_val(idx): return rs | {f} else: return rs | {f, idx} if z3.is_const(f): if z3.z3util.is_expr_val(f): return rs else: # variable return rs | {f} else: for f_ in f.children(): rs = get_vars(f_, rs) return set(rs)
def _get_vars(cls, f, rs): """ Helper method to obtain variables from a formula f recursively. Results are stored in the list rs. """ assert z3.is_expr(f) or z3.is_const(f), f if z3.is_const(f): if cls.is_var(f): rs.add(f) else: for c in f.children(): cls._get_vars(c, rs)
def z3_vars_in_formula(fml): """ Return all the variables in a Z3 formula. Following that in Z3 official repo. """ def visitor(e, seen): if e in seen: return seen[e] = True yield e if is_app(e): for ch in e.children(): for e in visitor(ch, seen): yield e return if is_quantifier(e): for e in visitor(e.body(), seen): yield e return seen = {} res = [] for e in visitor(fml, seen): if is_const(e) and e.decl().kind() == Z3_OP_UNINTERPRETED: #print("Variable", e) res.append(e) else: #print(e) pass return res
def f(_cache, e, seen): def f_cache(e): return _cache(f, e, seen) r = (z3.is_const(e) and e.decl().kind() == z3.Z3_OP_ANUM) or \ (e.num_args() > 0 and all(f_cache(c) for c in e.children())) return r
def partial_leaf_substitution(expr, substitution_dict): """Replaces consts/vars in `expr` according to `substitution_dict`. If a const/var is not in `substitution_dict.keys()`, it remains unchanged. >>> a, b, c = sl.list.locs("a b c") >>> subst = {b : c} >>> partial_leaf_substitution(sl.sepcon(sl.list("a"), sl.list("b")), subst) sl.sepcon(sl.list(a), sl.list(c)) >>> i, j = Ints("i j") >>> subst = {sl.alpha : i, sl.beta : j} >>> partial_leaf_substitution(sl.alpha < sl.beta, subst) i < j """ if z3.is_const(expr) or z3.is_var(expr): return substitution_dict.get(expr, expr) elif z3.is_app(expr): new_args = [ partial_leaf_substitution(child, substitution_dict) for child in expr.children() ] return replace_args(expr, new_args) else: assert (z3.is_quantifier(expr)) new_arg = partial_leaf_substitution(expr.body(), substitution_dict) return replace_args(expr, new_arg)
def const(value): """Syntactic sugar for `z3.is_const(simplify(value))`. i.e., return True iff `value` statically simplifies to a constant value. """ return z3.is_const(simplify(value))
def collect(f): if z3.is_const(f): if f.decl().kind() == z3.Z3_OP_UNINTERPRETED and not askey(f) in r: r.add(askey(f)) else: for c in f.children(): collect(c)
def is_term(a): """ Check if the input formula is a term. In FOL, terms are defined as term := const | var | f(t1,...,tn) where ti are terms. Examples: >>> from z3 import * >>> assert is_term(TRUE) >>> assert is_term(Bool('x')) >>> assert not is_term(And(Bool('x'),Bool('y'))) >>> assert not is_term(And(Bool('x'),Not(Bool('y')))) >>> assert is_term(IntVal(3)) >>> assert is_term(Int('x')) >>> assert is_term(Int('x') + Int('y')) >>> assert not is_term(Int('x') + Int('y') > 3) >>> assert not is_term(And(Int('x')==0,Int('y')==3)) >>> assert not is_term(Int('x')==0) >>> assert not is_term(3) >>> assert not is_term(Bool('x') == (Int('y')==Int('z'))) """ if not is_expr(a): return False if is_const(a): #covers both const value and var return True else: #covers f(t1,..,tn) return not is_bool(a) and all(is_term(c) for c in a.children())
def translate(self, expr, bound_variables=[]): if z3.is_const(expr): return self.mk_const(expr) # raise Z3_Unexpected_Expression('Unrecognized constant') elif z3.is_var(expr): # a de Bruijn indexed bound variable bv_length = len(bound_variables) return bound_variables[bv_length - z3.get_var_index(expr) - 1] elif z3.is_app(expr): args = [self.translate(expr.arg(i), bound_variables) for i in range(expr.num_args())] return self.mk_fun(expr.decl())(*args) # else: # raise Z3_Unexpected_Expression(expr) elif z3.is_quantifier(expr): num_vars = expr.num_vars() # vars = [language.const_dict[expr.var_name(i)] # for i in range(num_vars)] vars = [const(expr.var_name(i), self.mk_sort(expr.var_sort(i))) \ for i in range(num_vars)] new_bound_variables = bound_variables + vars body = self.translate(expr.body(), new_bound_variables) if expr.is_forall(): return forall(vars, body) else: return exists(vars, body) elif z3.is_func_decl(expr): return self.mk_fun(expr) else: print expr.kind raise Z3_Unexpected_Expression(expr)
def rec(e): if not z3.is_ast(e): return if z3.is_const(e) and e.decl().kind() == z3.Z3_OP_UNINTERPRETED: res.add(e) return for child in e.children(): rec(child)
def _is_literal(z3ast): if z3.is_int(z3ast): return z3.is_int_value(z3ast) if z3.is_bool(z3ast): return z3.is_true(z3ast) or z3.is_false(z3ast) if z3ast.sort_kind() == z3.Z3_UNINTERPRETED_SORT: return z3.is_const(z3ast) and '!' in str(z3ast) raise NotImplementedError('Don\'t know how to literal-check %s' % z3ast)
def _constify(struct, term): if isinstance(term, str): return struct.sort[term] else: assert z3.is_const(term), '{} : {} is no constant'.format( term, type(term).__name__) return term
def pp_app(self, a, d, xs): if z3.is_int_value(a): return self.pp_int(a) elif z3.is_rational_value(a): return self.pp_rational(a) elif z3.is_algebraic_value(a): return self.pp_algebraic(a) elif z3.is_bv_value(a): return self.pp_bv(a) elif z3.is_finite_domain_value(a): return self.pp_fd(a) elif z3.is_fprm_value(a): return self.pp_fprm_value(a) elif z3.is_fp_value(a): return self.pp_fp_value(a) elif z3.is_fp(a): return self.pp_fp(a, d, xs) elif z3.is_string_value(a): return self.pp_string(a) elif z3.is_const(a): return self.pp_const(a) else: f = a.decl() k = f.kind() if k == Z3_OP_POWER: return self.pp_power(a, d, xs) elif k == Z3_OP_DISTINCT: return self.pp_distinct(a, d, xs) elif k == Z3_OP_SELECT: return self.pp_select(a, d, xs) elif k == Z3_OP_SIGN_EXT or k == Z3_OP_ZERO_EXT or k == Z3_OP_REPEAT: return self.pp_unary_param(a, d, xs) elif k == Z3_OP_EXTRACT: return self.pp_extract(a, d, xs) elif k == Z3_OP_RE_LOOP: return self.pp_loop(a, d, xs) elif k == Z3_OP_DT_IS: return self.pp_is(a, d, xs) elif k == Z3_OP_ARRAY_MAP: return self.pp_map(a, d, xs) elif k == Z3_OP_CONST_ARRAY: return self.pp_K(a, d, xs) elif k == Z3_OP_PB_AT_MOST: return self.pp_atmost(a, d, f, xs) elif k == Z3_OP_PB_LE: return self.pp_pbcmp(a, d, f, xs) elif k == Z3_OP_PB_GE: return self.pp_pbcmp(a, d, f, xs) elif k == Z3_OP_PB_EQ: return self.pp_pbcmp(a, d, f, xs) elif z3.is_pattern(a): return self.pp_pattern(a, d, xs) elif self.is_infix(k): return self.pp_infix(a, d, xs) elif self.is_unary(k): return self.pp_unary(a, d, xs) else: return self.pp_prefix(a, d, xs)
def u_predicate(expr): if z3.is_const(expr) and expr.decl().kind() == z3.Z3_OP_UNINTERPRETED: return True decl = expr.decl() if decl is None or decl.kind() != z3.Z3_OP_UNINTERPRETED: return False for kid in expr.children(): i_formula(kid) return True
def substitute_taint(z3_expr): decl = z3_expr.decl() taint = set() if decl.kind() == z3.Z3_OP_ITE: # we need to differentiate in the case of ite statements cond_expr = z3_expr.children()[0] then_expr = z3_expr.children()[1] else_expr = z3_expr.children()[2] cond_expr, cond_taint = substitute_taint(cond_expr) # check if the cond expr is an ite statement after substitution # if the condition is tainted, do not even bother to evaluate the rest if cond_expr.decl().kind() != z3.Z3_OP_ITE and cond_taint: taint_const = z3.FreshConst(z3_expr.sort(), "taint") return taint_const, set([taint_const]) # evaluate the branches then_expr, then_taint = substitute_taint(then_expr) else_expr, else_taint = substitute_taint(else_expr) # check if the branches are an ite statement after substitution then_not_ite = then_expr.decl().kind() != z3.Z3_OP_ITE else_not_ite = else_expr.decl().kind() != z3.Z3_OP_ITE if (then_not_ite and else_not_ite) and (then_taint and else_taint): # both branches are fully tainted, replace and return taint_const = z3.FreshConst(z3_expr.sort(), "taint") return taint_const, set([taint_const]) # merge taints and create a new ite statement taint |= cond_taint | then_taint | else_taint if taint: z3_expr = z3.If(cond_expr, then_expr, else_expr) elif z3.is_const(z3_expr) and str(z3_expr) == "undefined": # the expression is tainted replace it # really dumb check, do not need anything else z3_expr = z3.FreshConst(z3_expr.sort(), "taint") taint.add(z3_expr) else: # remaining expressions are more complex, need to evaluate children child_list = z3_expr.children() for idx, child in enumerate(child_list): # iterate through members of the expr child, child_taint = substitute_taint(child) # replace entire expression if one non-ite member is tainted if child.decl().kind() != z3.Z3_OP_ITE and child_taint: # the expression is tainted replace it taint_const = z3.FreshConst(z3_expr.sort(), "taint") return taint_const, set([taint_const]) # members might also have changed, so update taint |= child_taint child_list[idx] = child if taint: # these are unfortunately necessary because AND/OR are "special" if decl.kind() == z3.Z3_OP_AND: z3_expr = z3.And(*child_list) elif decl.kind() == z3.Z3_OP_OR: z3_expr = z3.Or(*child_list) else: z3_expr = decl(*child_list) return z3_expr, taint
def substitute_taint(z3_expr, taints): decl = z3_expr.decl() if decl.kind() == z3.Z3_OP_ITE: # we need to differentiate in the case of ite statements cond_expr = z3_expr.children()[0] then_expr = z3_expr.children()[1] else_expr = z3_expr.children()[2] cond_expr, _ = substitute_taint(cond_expr, taints) then_expr, then_has_undefined = substitute_taint(then_expr, taints) else_expr, else_has_undefined = substitute_taint(else_expr, taints) if then_has_undefined and else_has_undefined: # both possibilities are tainted, replace taint = z3.FreshConst(then_expr.sort(), "taint") taints.append(taint) return taint, True # return the updated ite statement return z3.If(cond_expr, then_expr, else_expr), False if decl.kind() == z3.Z3_OP_DT_CONSTRUCTOR: # datatyperefs are not fully replaced, only their members child_list = z3_expr.children() for idx, child in enumerate(child_list): child, has_undefined = substitute_taint(child, taints) if has_undefined: # variabled is tainted, replace child = z3.FreshConst(child.sort(), "taint") taints.add(child) # members might also have changed, so update child_list[idx] = child return decl(*child_list), False if z3.is_const(z3_expr): # check if variable if not z3.z3util.is_expr_val(z3_expr) and str(z3_expr) == "undefined": # the expression is tainted replace it taint = z3.FreshConst(z3_expr.sort(), "taint") taints.add(taint) return taint, True return z3_expr, False child_list = z3_expr.children() for idx, child in enumerate(child_list): # iterate through members of the expr # replace entire expression if one member is tainted child, has_undefined = substitute_taint(child, taints) if has_undefined: # the expression is tainted replace it taint = z3.FreshConst(z3_expr.sort(), "taint") taints.add(taint) return taint, has_undefined # members might also have changed, so update child_list[idx] = child if decl.kind() == z3.Z3_OP_AND: return z3.And(*child_list), False if decl.kind() == z3.Z3_OP_OR: return z3.Or(*child_list), False return decl(*child_list), False
def pp_app(self, a, d, xs): if z3.is_int_value(a): return self.pp_int(a) elif z3.is_rational_value(a): return self.pp_rational(a) elif z3.is_algebraic_value(a): return self.pp_algebraic(a) elif z3.is_bv_value(a): return self.pp_bv(a) elif z3.is_finite_domain_value(a): return self.pp_fd(a) elif z3.is_fprm_value(a): return self.pp_fprm_value(a) elif z3.is_fp_value(a): return self.pp_fp_value(a) elif z3.is_fp(a): return self.pp_fp(a, d, xs) elif z3.is_string_value(a): return self.pp_string(a) elif z3.is_const(a): return self.pp_const(a) else: f = a.decl() k = f.kind() if k == Z3_OP_POWER: return self.pp_power(a, d, xs) elif k == Z3_OP_DISTINCT: return self.pp_distinct(a, d, xs) elif k == Z3_OP_SELECT: return self.pp_select(a, d, xs) elif k == Z3_OP_SIGN_EXT or k == Z3_OP_ZERO_EXT or k == Z3_OP_REPEAT: return self.pp_unary_param(a, d, xs) elif k == Z3_OP_EXTRACT: return self.pp_extract(a, d, xs) elif k == Z3_OP_DT_IS: return self.pp_is(a, d, xs) elif k == Z3_OP_ARRAY_MAP: return self.pp_map(a, d, xs) elif k == Z3_OP_CONST_ARRAY: return self.pp_K(a, d, xs) elif k == Z3_OP_PB_AT_MOST: return self.pp_atmost(a, d, f, xs) elif k == Z3_OP_PB_LE: return self.pp_pbcmp(a, d, f, xs) elif k == Z3_OP_PB_GE: return self.pp_pbcmp(a, d, f, xs) elif k == Z3_OP_PB_EQ: return self.pp_pbcmp(a, d, f, xs) elif z3.is_pattern(a): return self.pp_pattern(a, d, xs) elif self.is_infix(k): return self.pp_infix(a, d, xs) elif self.is_unary(k): return self.pp_unary(a, d, xs) else: return self.pp_prefix(a, d, xs)
def expr_fold_stateful(smt_expr, leaf, inner, update, state): assert (isinstance(smt_expr, z3.ExprRef)) if z3.is_const(smt_expr): return leaf(smt_expr, state) else: folding = [ expr_fold_stateful(c, leaf, inner, update, update(state)) for c in smt_expr.children() ] return inner(smt_expr, folding, state)
def __init__(self, rand: random.Random, expr: z3.ExprRef, solver: z3.Solver): if not solver_is_sat(solver): debug("Solver unexpectedly unsat; solver state:", solver.sexpr()) raise CrosshairInternal("Unexpected unsat from solver") self.condition_value = solver.model().evaluate(expr, model_completion=True) self._stats_key = f"realize_{expr}" if z3.is_const(expr) else None WorstResultNode.__init__(self, rand, expr == self.condition_value, solver)
def decl_to_string(decl): assert (isinstance(decl, z3.AstRef)) if isinstance(decl, z3.FuncDeclRef): dom = [str(decl.domain(i)) for i in range(decl.arity())] dom_str = ' * '.join(dom) rng = decl.range() return '{} : {} -> {}'.format(decl, dom_str, rng) else: assert (z3.is_const(decl)) return '{} : {} (const)'.format(decl, decl.sort())
def path_specific_expr(prefix, expr, var_mapping): """Creates a path specific copy of an expression, substituting all variables with path specific copies.""" assert z3.is_expr(expr), expr if z3.is_const(expr): return path_specific_var(prefix, expr, var_mapping) else: sub_map = {} for var in get_all_vars(expr): sub_map[var] = path_specific_var(prefix, var, var_mapping) return z3.substitute(expr, list(sub_map.items()))
def get_all_vars(expr): """Returns all variables in the expression.""" if z3.is_const(expr): if var_is_fixed(expr): return set() else: return {expr} assert expr.children() child_vars = set() for child_expr in expr.children(): child_vars |= get_all_vars(child_expr) return child_vars
def path_specific_var(prefix, var, var_mapping): """If var is not fixed, returns a renamed copy that can be constrained without affecting the original var, or copies with different prefixes. var_mapping caches all path specific variables.""" assert z3.is_const(var), var if var_is_fixed(var): # No ability or need to convert fixed values return var # Only currently need to support bitvecs, expand as needed. assert z3.is_bv(var), var return var_mapping.setdefault(var, z3.BitVec(prefix + str(var), var.size()))
def condition_addr(self, meta, addr, value): reg = self._addr_final_value_reg(addr) if isinstance(addr, int): name = f"*{hex(addr)}" else: name = addr expr = execution.final_register_value(f"Pf", reg, self.options.xlen) if isinstance(value, z3.BitVecRef) and not z3.is_const(value): addrs = {name} else: addrs = set() return expr == value, {name: expr}, addrs
def condition_reg(self, meta, thread, reg, value): # Herd and rmem always use the x version of the register reg = execution.x_register(reg) name = f"{thread}:{reg}" expr = execution.final_register_value( f"P{thread}", reg, self.options.xlen ) if isinstance(value, z3.BitVecRef) and not z3.is_const(value): addrs = {name} else: addrs = set() return expr == value, {name: expr}, addrs
def collect_consts(smt_expr): """Returns list of all constants (as ExprRef instances) that appear in the given expression""" assert (isinstance(smt_expr, z3.ExprRef)) non_unique_res = expr_fold(smt_expr, lambda t: [t] if not z3.is_int_value(t) else [], lambda _, cs: utils.flatten(cs)) for c in non_unique_res: assert (z3.is_const(c)) # Leaving the following in, in case conversion breaks again with strange z3 exceptions... #logger.info([c.__class__ for c in non_unique_res]) res = set(non_unique_res) #logger.info("Consts in expr: {}".format(res)) return [c for c in res if str(c) not in keywords]
def pp_fp(self, a, d, xs): _z3_assert(isinstance(a, z3.FPRef), "type mismatch") k = a.decl().kind() op = '?' if (self.fpa_pretty and k in _z3_op_to_fpa_pretty_str): op = _z3_op_to_fpa_pretty_str[k] elif k in _z3_op_to_fpa_normal_str: op = _z3_op_to_fpa_normal_str[k] elif k in _z3_op_to_str: op = _z3_op_to_str[k] n = a.num_args() if self.fpa_pretty: if self.is_infix(k) and n >= 3: rm = a.arg(0) if z3.is_fprm_value(rm) and z3.get_default_rounding_mode( a.ctx).eq(rm): arg1 = to_format(self.pp_expr(a.arg(1), d + 1, xs)) arg2 = to_format(self.pp_expr(a.arg(2), d + 1, xs)) r = [] r.append(arg1) r.append(to_format(' ')) r.append(to_format(op)) r.append(to_format(' ')) r.append(arg2) return compose(r) elif k == Z3_OP_FPA_NEG: return compose([ to_format('-'), to_format(self.pp_expr(a.arg(0), d + 1, xs)) ]) if k in _z3_op_to_fpa_normal_str: op = _z3_op_to_fpa_normal_str[k] r = [] r.append(to_format(op)) if not z3.is_const(a): r.append(to_format('(')) first = True for c in a.children(): if first: first = False else: r.append(to_format(', ')) r.append(self.pp_expr(c, d + 1, xs)) r.append(to_format(')')) return compose(r) else: return to_format(a.as_string())
def variables_in_expression(expression): expressions = [expression] variables = [] while len(expressions) > 0: expression = expressions.pop(0) if z3.is_const(expression): if not z3.is_bool_or_int_value(expression): variables.append(expression) elif z3.is_app(expression): if expression.decl().kind() == z3.Z3_OP_UNINTERPRETED: variables.append(expression.decl()) for i in range(expression.num_args()): expressions.append(expression.arg(i)) return variables
def expr_fold(smt_expr, leaf, inner): """Folding the given expression (sexpr tree) by applying the leaf function to each leaf and the inner function at each inner node. :param smt_expr: z3 ExprRef :param leaf: Function from (constants) ExprRef to rtype :param inner: Function from (non-const) ExpRef and list of rtype to rtype """ assert (isinstance(smt_expr, z3.ExprRef)) if z3.is_const(smt_expr): res = leaf(smt_expr) return res else: folding = [expr_fold(c, leaf, inner) for c in smt_expr.children()] return inner(smt_expr, folding)
def toDimacs(self, clause, neg=False): variables = [] #print(clause) if z3.is_const(clause): if not isinstance(clause, IntNumRef): variables.append(self.getVarIndex(str(clause))) else: sys.exit("shouldn't get here") for c in clause.children(): if is_not(c): print("AAAA"); variables = variables + self.toDimacs(c) return variables
def rec(e): if isinstance(e, z3.QuantifierRef): for n in range(e.num_vars()): mkvar(e.var_name(n), e.var_sort(n)) elif z3.is_algebraic_value(e) or \ z3.is_bv_value(e) or \ z3.is_int_value(e) or \ z3.is_rational_value(e): pass elif z3.is_const(e): mkvar(str(e), e.sort()) for sub in e.children(): rec(sub)
def is_function_symbol(s: z3.ExprRef) -> bool: if not z3.is_app(s): return False if z3.is_const(s): return False func = s.decl() if func.range() == z3.BoolSort(): # predicate symbol return False if func.name().lower() == 'if': return False return True
def pp_fp(self, a, d, xs): z3._z3_assert(isinstance(a, z3.FPRef), "type mismatch") k = a.decl().kind() op = '?' if (self.fpa_pretty and k in _z3_op_to_fpa_pretty_str): op = _z3_op_to_fpa_pretty_str[k] elif k in _z3_op_to_fpa_normal_str: op = _z3_op_to_fpa_normal_str[k] elif k in _z3_op_to_str: op = _z3_op_to_str[k] n = a.num_args() if self.fpa_pretty: if self.is_infix(k) and n >= 3: rm = a.arg(0) if z3.is_fprm_value(rm) and z3._dflt_rm(a.ctx).eq(rm): arg1 = to_format(self.pp_expr(a.arg(1), d+1, xs)) arg2 = to_format(self.pp_expr(a.arg(2), d+1, xs)) r = [] r.append(arg1) r.append(to_format(' ')) r.append(to_format(op)) r.append(to_format(' ')) r.append(arg2) return compose(r) elif k == Z3_OP_FPA_NEG: return compose([to_format('-') , to_format(self.pp_expr(a.arg(0), d+1, xs))]) if k in _z3_op_to_fpa_normal_str: op = _z3_op_to_fpa_normal_str[k] r = [] r.append(to_format(op)) if not z3.is_const(a): r.append(to_format('(')) first = True for c in a.children(): if first: first = False else: r.append(to_format(', ')) r.append(self.pp_expr(c, d+1, xs)) r.append(to_format(')')) return compose(r) else: return to_format(a.as_string())
def pp_app(self, a, d, xs): if z3.is_int_value(a): return self.pp_int(a) elif z3.is_rational_value(a): rat = self.pp_rational(a) return rat elif z3.is_algebraic_value(a): return self.pp_algebraic(a) elif z3.is_bv_value(a): return self.pp_bv(a) elif z3.is_const(a): return self.pp_const(a) else: f = a.decl() k = f.kind() if k == Z3_OP_POWER: return self.pp_power(a, d, xs) elif k == Z3_OP_DISTINCT: return self.pp_distinct(a, d, xs) elif k == Z3_OP_SELECT: return self.pp_select(a, d, xs) elif k == Z3_OP_SIGN_EXT or k == Z3_OP_ZERO_EXT or k == Z3_OP_REPEAT: return self.pp_unary_param(a, d, xs) elif k == Z3_OP_EXTRACT: return self.pp_extract(a, d, xs) elif k == Z3_OP_ARRAY_MAP: return self.pp_map(a, d, xs) elif k == Z3_OP_CONST_ARRAY: return self.pp_K(a, d, xs) elif z3.is_pattern(a): return self.pp_pattern(a, d, xs) elif self.is_infix(k): return self.pp_infix(a, d, xs) elif self.is_unary(k): return self.pp_unary(a, d, xs) else: return self.pp_prefix(a, d, xs)
def _back_single_term(self, expr, args, model=None): assert z3.is_expr(expr) if z3.is_quantifier(expr): raise NotImplementedError( "Quantified back conversion is currently not supported") assert not len(args) > 2 or \ (z3.is_and(expr) or z3.is_or(expr) or z3.is_add(expr) or z3.is_mul(expr) or (len(args) == 3 and (z3.is_ite(expr) or z3.is_array_store(expr)))),\ "Unexpected n-ary term: %s" % expr res = None try: decl = z3.Z3_get_app_decl(expr.ctx_ref(), expr.as_ast()) kind = z3.Z3_get_decl_kind(expr.ctx.ref(), decl) # Try to get the back-conversion function for the given Kind fun = self._back_fun[kind] return fun(args, expr) except KeyError as ex: pass if z3.is_const(expr): # Const or Symbol if z3.is_rational_value(expr): n = expr.numerator_as_long() d = expr.denominator_as_long() f = Fraction(n, d) return self.mgr.Real(f) elif z3.is_int_value(expr): n = expr.as_long() return self.mgr.Int(n) elif z3.is_bv_value(expr): n = expr.as_long() w = expr.size() return self.mgr.BV(n, w) elif z3.is_as_array(expr): if model is None: raise NotImplementedError("As-array expressions cannot be" \ " handled as they are not " \ "self-contained") else: interp_decl = z3.get_as_array_func(expr) interp = model[interp_decl] default = self.back(interp.else_value(), model=model) assign = {} for i in xrange(interp.num_entries()): e = interp.entry(i) assert e.num_args() == 1 idx = self.back(e.arg_value(0), model=model) val = self.back(e.value(), model=model) assign[idx] = val arr_type = self._z3_to_type(expr.sort()) return self.mgr.Array(arr_type.index_type, default, assign) elif z3.is_algebraic_value(expr): # Algebraic value return self.mgr._Algebraic(Numeral(expr)) else: # it must be a symbol try: return self.mgr.get_symbol(str(expr)) except UndefinedSymbolError: import warnings symb_type = self._z3_to_type(expr.sort()) warnings.warn("Defining new symbol: %s" % str(expr)) return self.mgr.FreshSymbol(symb_type, template="__z3_%d") elif z3.is_function(expr): # This needs to be after we try to convert regular Symbols fsymbol = self.mgr.get_symbol(expr.decl().name()) return self.mgr.Function(fsymbol, args) # If we reach this point, we did not manage to translate the expression raise ConvertExpressionError(message=("Unsupported expression: %s" % (str(expr))), expression=expr)
def _back_single_term(self, expr, args, model=None): assert z3.is_expr(expr) if z3.is_quantifier(expr): raise NotImplementedError( "Quantified back conversion is currently not supported") res = None if z3.is_and(expr): res = self.mgr.And(args) elif z3.is_or(expr): res = self.mgr.Or(args) elif z3.is_add(expr): res = self.mgr.Plus(args) elif z3.is_div(expr): res = self.mgr.Div(args[0], args[1]) elif z3.is_eq(expr): if self._get_type(args[0]).is_bool_type(): res = self.mgr.Iff(args[0], args[1]) else: res = self.mgr.Equals(args[0], args[1]) elif z3.is_iff(expr): res = self.mgr.Iff(args[0], args[1]) elif z3.is_xor(expr): res = self.mgr.Xor(args[0], args[1]) elif z3.is_false(expr): res = self.mgr.FALSE() elif z3.is_true(expr): res = self.mgr.TRUE() elif z3.is_gt(expr): res = self.mgr.GT(args[0], args[1]) elif z3.is_ge(expr): res = self.mgr.GE(args[0], args[1]) elif z3.is_lt(expr): res = self.mgr.LT(args[0], args[1]) elif z3.is_le(expr): res = self.mgr.LE(args[0], args[1]) elif z3.is_mul(expr): res = self.mgr.Times(args[0], args[1]) elif z3.is_uminus(expr): tp = self._get_type(args[0]) if tp.is_real_type(): minus_one = self.mgr.Real(-1) else: assert tp.is_int_type() minus_one = self.mgr.Int(-1) res = self.mgr.Times(args[0], minus_one) elif z3.is_sub(expr): res = self.mgr.Minus(args[0], args[1]) elif z3.is_not(expr): res = self.mgr.Not(args[0]) elif z3.is_implies(expr): res = self.mgr.Implies(args[0], args[1]) elif z3.is_quantifier(expr): raise NotImplementedError elif z3.is_const(expr): if z3.is_rational_value(expr): n = expr.numerator_as_long() d = expr.denominator_as_long() f = Fraction(n, d) res = self.mgr.Real(f) elif z3.is_int_value(expr): n = expr.as_long() res = self.mgr.Int(n) elif z3.is_bv_value(expr): n = expr.as_long() w = expr.size() res = self.mgr.BV(n, w) elif z3.is_as_array(expr): if model is None: raise NotImplementedError("As-array expressions cannot be" \ " handled as they are not " \ "self-contained") else: interp_decl = z3.get_as_array_func(expr) interp = model[interp_decl] default = self.back(interp.else_value(), model=model) assign = {} for i in xrange(interp.num_entries()): e = interp.entry(i) assert e.num_args() == 1 idx = self.back(e.arg_value(0), model=model) val = self.back(e.value(), model=model) assign[idx] = val arr_type = self._z3_to_type(expr.sort()) res = self.mgr.Array(arr_type.index_type, default, assign) elif z3.is_algebraic_value(expr): # Algebraic value return self.mgr._Algebraic(Numeral(expr)) else: # it must be a symbol res = self.mgr.get_symbol(str(expr)) elif z3.is_ite(expr): res = self.mgr.Ite(args[0], args[1], args[2]) elif z3.is_function(expr): res = self.mgr.Function(self.mgr.get_symbol(expr.decl().name()), args) elif z3.is_to_real(expr): res = self.mgr.ToReal(args[0]) elif z3.is_bv_and(expr): res = self.mgr.BVAnd(args[0], args[1]) elif z3.is_bv_or(expr): res = self.mgr.BVOr(args[0], args[1]) elif z3.is_bv_xor(expr): res = self.mgr.BVXor(args[0], args[1]) elif z3.is_bv_not(expr): res = self.mgr.BVNot(args[0]) elif z3.is_bv_neg(expr): res = self.mgr.BVNeg(args[0]) elif z3.is_bv_concat(expr): res = self.mgr.BVConcat(args[0], args[1]) elif z3.is_bv_ult(expr): res = self.mgr.BVULT(args[0], args[1]) elif z3.is_bv_uleq(expr): res = self.mgr.BVULE(args[0], args[1]) elif z3.is_bv_slt(expr): res = self.mgr.BVSLT(args[0], args[1]) elif z3.is_bv_sleq(expr): res = self.mgr.BVSLE(args[0], args[1]) elif z3.is_bv_ugt(expr): res = self.mgr.BVUGT(args[0], args[1]) elif z3.is_bv_ugeq(expr): res = self.mgr.BVUGE(args[0], args[1]) elif z3.is_bv_sgt(expr): res = self.mgr.BVSGT(args[0], args[1]) elif z3.is_bv_sgeq(expr): res = self.mgr.BVSGE(args[0], args[1]) elif z3.is_bv_extract(expr): end = z3.get_payload(expr, 0) start = z3.get_payload(expr, 1) res = self.mgr.BVExtract(args[0], start, end) elif z3.is_bv_add(expr): res = self.mgr.BVAdd(args[0], args[1]) elif z3.is_bv_mul(expr): res = self.mgr.BVMul(args[0], args[1]) elif z3.is_bv_udiv(expr): res = self.mgr.BVUDiv(args[0], args[1]) elif z3.is_bv_sdiv(expr): res = self.mgr.BVSDiv(args[0], args[1]) elif z3.is_bv_urem(expr): res = self.mgr.BVURem(args[0], args[1]) elif z3.is_bv_srem(expr): res = self.mgr.BVSRem(args[0], args[1]) elif z3.is_bv_lshl(expr): res = self.mgr.BVLShl(args[0], args[1]) elif z3.is_bv_lshr(expr): res = self.mgr.BVLShr(args[0], args[1]) elif z3.is_bv_ashr(expr): res = self.mgr.BVAShr(args[0], args[1]) elif z3.is_bv_sub(expr): res = self.mgr.BVSub(args[0], args[1]) elif z3.is_bv_rol(expr): amount = z3.get_payload(expr, 0) res = self.mgr.BVRol(args[0], amount) elif z3.is_bv_ror(expr): amount = z3.get_payload(expr, 0) res = self.mgr.BVRor(args[0], amount) elif z3.is_bv_ext_rol(expr): amount = args[1].bv_unsigned_value() res = self.mgr.BVRol(args[0], amount) elif z3.is_bv_ext_ror(expr): amount = args[1].bv_unsigned_value() res = self.mgr.BVRor(args[0], amount) elif z3.is_bv_sext(expr): amount = z3.get_payload(expr, 0) res = self.mgr.BVSExt(args[0], amount) elif z3.is_bv_zext(expr): amount = z3.get_payload(expr, 0) res = self.mgr.BVZExt(args[0], amount) elif z3.is_array_select(expr): res = self.mgr.Select(args[0], args[1]) elif z3.is_array_store(expr): res = self.mgr.Store(args[0], args[1], args[2]) elif z3.is_const_array(expr): arr_ty = self._z3_to_type(expr.sort()) k = args[0] res = self.mgr.Array(arr_ty.index_type, k) elif z3.is_power(expr): res = self.mgr.Pow(args[0], args[1]) if res is None: raise ConvertExpressionError(message=("Unsupported expression: %s" % str(expr)), expression=expr) return res
print "error = {}".format(error) axioms += forward_clauses(axioms,inflex) init_z3 = sv.clauses_to_z3(init) print "init_z3 = {}".format(init_z3) for a in updates: print lu.simplify_clauses(a[1]) rho_z3 = z3.Or(*[sv.clauses_to_z3(lu.simplify_clauses(a[1])) for a in updates]) print "rho_z3 = {}".format(rho_z3) bad_z3 = sv.clauses_to_z3(error) print "bad_z3 = {}".format(bad_z3) background_z3 = sv.clauses_to_z3(axioms) print "background_z3 = {}".format(background_z3) #relations_z3 = [ns(rel) for rel in sig.relations if tr.is_new(rel) or rel in inflex] relations_z3 = [ x for x in gsyms if not z3.is_const(x) or (z3.is_const(x) and x.sort() == z3.BoolSort()) ] relations_z3 += [ x for _,x in lsyms if not z3.is_const(x) or (z3.is_const(x) and x.sort() == z3.BoolSort()) ] print "relations_z3 = {}".format(relations_z3) ### HACK: remove skolem predicates from the list of predicate symbols #relations_z3 = [ x for x in relations_z3 if not x in skolems ] pdr = pd.PDR(init_z3, rho_z3, bad_z3, background_z3, gsyms, lsyms, relations_z3, True) watch = Stopwatch() with watch: outcome = pdr.run() if outcome: status = "valid" if hasattr(pdr, 'verify') and not pdr.verify(outcome):
def _back_single_term(self, expr, args): assert z3.is_expr(expr) if z3.is_quantifier(expr): raise NotImplementedError( "Quantified back conversion is currently not supported") res = None if z3.is_and(expr): res = self.mgr.And(args) elif z3.is_or(expr): res = self.mgr.Or(args) elif z3.is_add(expr): res = self.mgr.Plus(args) elif z3.is_div(expr): res = self.mgr.Div(args[0], args[1]) elif z3.is_eq(expr): if self._get_type(args[0]).is_bool_type(): res = self.mgr.Iff(args[0], args[1]) else: res = self.mgr.Equals(args[0], args[1]) elif z3.is_iff(expr): res = self.mgr.Iff(args[0], args[1]) elif z3.is_xor(expr): res = self.mgr.Xor(args[0], args[1]) elif z3.is_false(expr): res = self.mgr.FALSE() elif z3.is_true(expr): res = self.mgr.TRUE() elif z3.is_gt(expr): res = self.mgr.GT(args[0], args[1]) elif z3.is_ge(expr): res = self.mgr.GE(args[0], args[1]) elif z3.is_lt(expr): res = self.mgr.LT(args[0], args[1]) elif z3.is_le(expr): res = self.mgr.LE(args[0], args[1]) elif z3.is_mul(expr): res = self.mgr.Times(args[0], args[1]) elif z3.is_uminus(expr): tp = self._get_type(args[0]) if tp.is_real_type(): minus_one = self.mgr.Real(-1) else: assert tp.is_int_type() minus_one = self.mgr.Int(-1) res = self.mgr.Times(args[0], minus_one) elif z3.is_sub(expr): res = self.mgr.Minus(args[0], args[1]) elif z3.is_not(expr): res = self.mgr.Not(args[0]) elif z3.is_implies(expr): res = self.mgr.Implies(args[0], args[1]) elif z3.is_quantifier(expr): raise NotImplementedError elif z3.is_const(expr): if z3.is_rational_value(expr): n = expr.numerator_as_long() d = expr.denominator_as_long() f = Fraction(n, d) res = self.mgr.Real(f) elif z3.is_int_value(expr): n = expr.as_long() res = self.mgr.Int(n) elif z3.is_bv_value(expr): n = expr.as_long() w = expr.size() res = self.mgr.BV(n, w) else: # it must be a symbol res = self.mgr.get_symbol(str(expr)) elif z3.is_ite(expr): res = self.mgr.Ite(args[0], args[1], args[2]) elif z3.is_function(expr): res = self.mgr.Function(self.mgr.get_symbol(expr.decl().name()), args) elif z3.is_to_real(expr): res = self.mgr.ToReal(args[0]) elif z3.is_bv_and(expr): res = self.mgr.BVAnd(args[0], args[1]) elif z3.is_bv_or(expr): res = self.mgr.BVOr(args[0], args[1]) elif z3.is_bv_xor(expr): res = self.mgr.BVXor(args[0], args[1]) elif z3.is_bv_not(expr): res = self.mgr.BVNot(args[0]) elif z3.is_bv_neg(expr): res = self.mgr.BVNeg(args[0]) elif z3.is_bv_concat(expr): res = self.mgr.BVConcat(args[0], args[1]) elif z3.is_bv_ult(expr): res = self.mgr.BVULT(args[0], args[1]) elif z3.is_bv_uleq(expr): res = self.mgr.BVULE(args[0], args[1]) elif z3.is_bv_slt(expr): res = self.mgr.BVSLT(args[0], args[1]) elif z3.is_bv_sleq(expr): res = self.mgr.BVSLE(args[0], args[1]) elif z3.is_bv_ugt(expr): res = self.mgr.BVUGT(args[0], args[1]) elif z3.is_bv_ugeq(expr): res = self.mgr.BVUGE(args[0], args[1]) elif z3.is_bv_sgt(expr): res = self.mgr.BVSGT(args[0], args[1]) elif z3.is_bv_sgeq(expr): res = self.mgr.BVSGE(args[0], args[1]) elif z3.is_bv_extract(expr): end = z3.get_payload(expr, 0) start = z3.get_payload(expr, 1) res = self.mgr.BVExtract(args[0], start, end) elif z3.is_bv_add(expr): res = self.mgr.BVAdd(args[0], args[1]) elif z3.is_bv_mul(expr): res = self.mgr.BVMul(args[0], args[1]) elif z3.is_bv_udiv(expr): res = self.mgr.BVUDiv(args[0], args[1]) elif z3.is_bv_sdiv(expr): res = self.mgr.BVSDiv(args[0], args[1]) elif z3.is_bv_urem(expr): res = self.mgr.BVURem(args[0], args[1]) elif z3.is_bv_srem(expr): res = self.mgr.BVSRem(args[0], args[1]) elif z3.is_bv_lshl(expr): res = self.mgr.BVLShl(args[0], args[1]) elif z3.is_bv_lshr(expr): res = self.mgr.BVLShr(args[0], args[1]) elif z3.is_bv_ashr(expr): res = self.mgr.BVAShr(args[0], args[1]) elif z3.is_bv_sub(expr): res = self.mgr.BVSub(args[0], args[1]) elif z3.is_bv_rol(expr): amount = z3.get_payload(expr, 0) res = self.mgr.BVRol(args[0], amount) elif z3.is_bv_ror(expr): amount = z3.get_payload(expr, 0) res = self.mgr.BVRor(args[0], amount) elif z3.is_bv_ext_rol(expr): amount = args[1].bv_unsigned_value() res = self.mgr.BVRol(args[0], amount) elif z3.is_bv_ext_ror(expr): amount = args[1].bv_unsigned_value() res = self.mgr.BVRor(args[0], amount) elif z3.is_bv_sext(expr): amount = z3.get_payload(expr, 0) res = self.mgr.BVSExt(args[0], amount) elif z3.is_bv_zext(expr): amount = z3.get_payload(expr, 0) res = self.mgr.BVZExt(args[0], amount) if res is None: raise ConvertExpressionError(message=("Unsupported expression: %s" % str(expr)), expression=expr) return res