def generalize(f, ss, maxV, minV): assert z3.is_expr(f), f assert isinstance(ss, set) and all(z3.is_expr(x) for x in ss), ss ofs = Miscs.getTermsFixedCoefs(ss, 2) ofs = [OctForm.convert(of) for of in ofs] #octagonal forms #fExprs = [f.expr for f in fs] ofs = [(of, of.mkUbExpr(maxV)) for of in ofs] rs = [(of, SMT.check(f, ubExpr)) for (of, ubExpr) in ofs] rs = [(of, cexs) for (of, (cexs, isSucc)) in rs if SMT.getStat(cexs, isSucc) != SMT.DISPROVED] def _f(octForm): statsd = {maxV: SMT.PROVED} boundV = gc(f, octForm, minV, maxV, statsd) if boundV not in statsd or statsd[boundV] != SMT.DISPROVED: return boundV else: return None print "compute upperbounds for {} oct terms".format(len(rs)) ubVs = [(of, _f(of)) for (of, _) in rs] ubVs = [(of, v) for (of, v) in ubVs if v is not None] return ubVs
def mcheck_d(self, loc, inv, inps, ncexs): assert isinstance(loc, str), loc assert inv is None or isinstance( inv, data.inv.base.Inv) or z3.is_expr(inv), inv assert inps is None or isinstance(inps, data.traces.Inps), inps assert ncexs >= 1, ncexs try: inv_expr = inv.expr(self.use_reals) if inv_expr is zFalse: inv_expr = None except AttributeError: if z3.is_expr(inv): inv_expr = inv else: inv_expr = None if settings.DO_INCR_DEPTH: cexs, is_succ = self.mcheck_depth(self[loc], inv, inv_expr, inps, ncexs) else: cexs, is_succ, stat = self.mcheck( self.get_ss_at_depth(self[loc], depth=None), inv_expr, inps, ncexs) return cexs, is_succ
def __init__(self, init_conds, defs, input_vars, assumes): """ This class models a program using 1. initial condition 2. transition (definitions of updated variables) 3. assumptions Input variables: - init_cond: list of initial conditions e.g. [Block == Off,Reset == On,WaterPres == wp_init_val, Overridden == False,SafetyInjection == On,Pressure == TooLow] - defs: a dictionary consisting variables being updated by the transition - input_vars: variables that are INDEPDENT. SCR programs don't have these, because input (monitored) vars are dependent due to OIA - assumes: list of assumptions Two types of assumptions: (1) state assumes: those for each *state* e.g. And(0 <= WaterPres,WaterPres < 2000): WaterPres is in range 0,2000 at any state (2) trans assumes: those for each *transition* e.g. One Input Assumption asserts only 1 var can changed at a time or And(pre(WaterPres) - 10 <= WaterPres, WaterPres <= pre(WaterPres) + 10) """ if __debug__: assert is_list(init_conds) and \ all(is_state(c) for c in init_conds), init_conds assert is_dict(defs) and \ all(is_expr(v) for v in defs.values()), defs assert is_list(input_vars) and \ all(is_expr_var(v) for v in input_vars), input_vars assert is_list(assumes) and \ all(is_expr(a) for a in assumes), assumes self.defs = defs self.init_conds = init_conds self.input_vars = input_vars self.assumes_state = [] self.assumes_trans = [] for a in assumes: Prog.append_f(a, self.assumes_state, self.assumes_trans) #Known invariants (lemmas). Use add_inv() to add an inv as lemma self.invs_state = [] self.invs_trans = []
def detect_unhandled_exception(self, previous_instruction, current_instruction, tainted_record): # Register all exceptions if previous_instruction and previous_instruction["op"] in [ "CALL", "CALLCODE", "DELEGATECALL", "STATICCALL" ] and convert_stack_value_to_int( current_instruction["stack"][-1]) == 1: if tainted_record and tainted_record.stack and tainted_record.stack[ -1] and is_expr(tainted_record.stack[-1][0]): self.exceptions[tainted_record.stack[-1] [0]] = previous_instruction["pc"] # Remove all handled exceptions elif current_instruction["op"] == "JUMPI" and self.exceptions: if tainted_record and tainted_record.stack and tainted_record.stack[ -2] and is_expr(tainted_record.stack[-2][0]): for var in get_vars(tainted_record.stack[-2][0]): if var in self.exceptions: del self.exceptions[var] # Report all unhandled exceptions at termination elif current_instruction["op"] in [ "RETURN", "STOP", "SUICIDE", "SELFDESTRUCT" ] and self.exceptions: for exception in self.exceptions: return self.exceptions[exception] return None
def detect_arbitrary_memory_access(self, tainted_record, individual, current_instruction): if current_instruction["op"] == "SSTORE": if tainted_record and tainted_record.stack: tainted_index = tainted_record.stack[-1] tainted_value = tainted_record.stack[-2] if tainted_index and tainted_value and is_expr( tainted_index[0]) and is_expr(tainted_value[0]): if get_vars(tainted_index[0]) and get_vars( tainted_value[0]): tainted_index_var = get_vars(tainted_index[0])[0] tainted_value_var = get_vars(tainted_value[0])[0] if tainted_index != tainted_value and "calldataload_" in str( tainted_index[0]) and "calldataload_" in str( tainted_value[0]): if len(str(tainted_index_var).split("_")) == 3: transaction_index = int( str(tainted_index_var).split("_")[1]) argument_index = int( str(tainted_index_var).split("_")[2]) + 1 if type(individual. chromosome[transaction_index] ["arguments"][argument_index] ) is int and individual.chromosome[ transaction_index]["arguments"][ argument_index] > 2**128 - 1: return current_instruction["pc"] return None
def to_z3(p): typ = "{} = z3.Ints('{}')" vs = map(str, get_vars(p)) z3_vars_decl = typ.format(','.join(vs),' '.join(vs)) exec(z3_vars_decl) f = eval(str(p)) print f print z3.is_expr(f)
def to_z3(p): print("WARN: deprecated, don't use eval()") typ = "{} = z3.Ints('{}')" vs = map(str, get_vars(p)) z3_vars_decl = typ.format(','.join(vs),' '.join(vs)) exec(z3_vars_decl) f = eval(str(p)) print z3.is_expr(f)
def _coerce_exprs(a, b, ctx=None): if not z3.is_expr(a) and not z3.is_expr(b): a = _py2expr(a, ctx) b = _py2expr(b, ctx) s = None s = _coerce_expr_merge(s, a) s = _coerce_expr_merge(s, b) a = s.cast(a) b = s.cast(b) return (a, b)
def expr_member_smt(f, gs): """ Check if a formula f is in the list gs using SMT. >>> z = Bool('z') >>> expr_member_smt(z, [Not(Not(z))]) True """ assert is_expr(f), f assert all(is_expr(g) for g in gs), gs return any(is_equiv(f, g) for g in gs)
def __init__(self, expr, label=None): assert z3.is_expr(expr) or isinstance(expr, LabeledExpr), expr if z3.is_expr(expr): self.expr = expr else: self.expr = expr.expr if label: self.label = label elif z3.is_expr(expr): self.label = None else: self.label = expr.label
def is_imply(f, g, solver=None): """ >>> from z3 import * >>> x, y = Ints('x y') >>> assert is_imply(x >= 3, x >= -5) """ assert is_expr(f) assert is_expr(g) if fhash(f) == fhash(g): return True else: return is_tautology(Implies(f, g), solver)
def detect_transaction_order_dependency(self, current_instruction, tainted_record, individual, transaction_index): if current_instruction["op"] == "SSTORE": if tainted_record and tainted_record.stack and tainted_record.stack[ -2] and is_expr(tainted_record.stack[-2][0]): index = convert_stack_value_to_int( current_instruction["stack"][-1]) if index not in self.sstores: self.sstores[index] = ( tainted_record.stack[-2][0], individual.chromosome[transaction_index]["arguments"] [0], individual.solution[transaction_index] ["transaction"]["from"], current_instruction["pc"]) elif current_instruction["op"] == "SLOAD": index = convert_stack_value_to_int( current_instruction["stack"][-1]) if index in self.sstores and self.sstores[index][ 1] != individual.chromosome[transaction_index][ "arguments"][0]: self.sloads[index] = ( self.sstores[index][0], individual.chromosome[transaction_index]["arguments"][0], individual.solution[transaction_index]["transaction"] ["from"], self.sstores[index][3]) elif current_instruction["op"] == "CALL": if tainted_record and tainted_record.stack and tainted_record.stack[ -3] and is_expr(tainted_record.stack[-3][0]): for index in self.sloads: if index in self.sstores and self.sloads[index][ 0] == tainted_record.stack[-3][0] and self.sloads[ index][1] == individual.chromosome[ transaction_index]["arguments"][0]: return self.sloads[index][3] if tainted_record and tainted_record.stack and tainted_record.stack[ -2]: value = convert_stack_value_to_int( current_instruction["stack"][-3]) if value > 0 or tainted_record and tainted_record.stack and tainted_record.stack[ -3]: for i in range(transaction_index + 1, len(individual.chromosome)): if self.sstores and individual.chromosome[ transaction_index][ "arguments"] == individual.chromosome[i][ "arguments"] and individual.solution[ transaction_index]["transaction"][ "from"] != individual.solution[ i]["transaction"]["from"]: return list(self.sstores.values())[0][-1] return None
def maximize(self, loc, term_expr, extra_constr=None): """ maximize value of term """ assert z3.is_expr(term_expr), term_expr assert extra_constr is None or \ z3.is_expr(extra_constr), extra_constr if settings.DO_INCR_DEPTH: v, stat = self.mmaximize_depth(self[loc], term_expr, extra_constr) else: v, stat = self.mmaximize( self.get_ss_at_depth(self[loc], depth=None), term_expr) return v
def _imply(cls, fs, g, is_conj=True): assert z3.is_expr(g), g if is_conj: # And(fs) => g if z3.is_expr(fs): claim = z3.Implies(fs, g) else: claim = z3.Implies(z3.And(fs), g) else: # g => Or(fs) if z3.is_expr(fs): claim = z3.Implies(g, fs) else: claim = z3.Implies(g, z3.Or(fs)) models, _ = cls.get_models(z3.Not(claim), k=1) return models is False
def main(self, a): if z3.is_expr(a): return self.pp_expr(a, 0, []) elif z3.is_sort(a): return self.pp_sort(a) elif z3.is_func_decl(a): return self.pp_decl(a) elif isinstance(a, z3.Goal) or isinstance(a, z3.AstVector): return self.pp_seq(a, 0, []) elif isinstance(a, z3.Solver): return self.pp_seq(a.assertions(), 0, []) elif isinstance(a, z3.Fixedpoint): return a.sexpr() elif isinstance(a, z3.Optimize): return a.sexpr() elif isinstance(a, z3.ApplyResult): return self.pp_seq_seq(a, 0, []) elif isinstance(a, z3.ModelRef): return self.pp_model(a) elif isinstance(a, z3.FuncInterp): return self.pp_func_interp(a) elif isinstance(a, list) or isinstance(a, tuple): return self.pp_list(a) else: return to_format(self.pp_unknown())
def If(cond, a, b): """ Conceptually computes ite(cond, a, b) but try to simplify out the ite if possible and supports more than just plain z3 datatypes. """ if not z3.is_expr(cond): raise ValueError("util.If: Expected cond to be a z3 expression, got {!r}".format(cond)) cond = simplify(cond) if is_true(cond): return a if is_false(cond): return b if hasattr(a, 'size') and hasattr(b, 'size'): assert a.size() == b.size( ), "Can not ite types of different size {} v. {}".format(a.size(), b.size()) if definitely_equal(a, b): return a if hasattr(a, 'ite'): assert type(a) == type(b), "{} v {}".format(type(a), type(b)) return a.ite(b, cond) is_z3_func = z3.is_func_decl(a) or z3.is_func_decl(b) is_py_func = isinstance(a, types.FunctionType) or isinstance(b, types.FunctionType) if is_z3_func or is_py_func: if not isinstance(a, types.FunctionType) and not isinstance(a, z3.FuncDeclRef): a = (lambda outer: lambda *args, **kwargs: outer)(a) if not isinstance(b, types.FunctionType) and not isinstance(b, z3.FuncDeclRef): b = (lambda outer: lambda *args, **kwargs: outer)(b) return lambda *args, **kwargs: If(cond, a(*args, **kwargs), b(*args, **kwargs)) if isinstance(a, dict) and isinstance(b, dict): # For simplicity, only ite dicts with exactly the same keys # and only if their values can be ite'd assert set(a.keys()) == set(b.keys()), 'Can not ite different dicts {} v. {}'.format(a.keys(), b.keys()) c = {} for k in a.keys(): c[k] = If(cond, a[k], b[k]) return c if isinstance(a, list): a = tuple(a) if isinstance(b, list): b = tuple(b) if isinstance(a, tuple) and isinstance(b, tuple): # For simplicity, only ite tuples of same length # and only if their values can be ite'd assert len(a) == len(b), 'Can not ite tuples of different length {} v. {}'.format(len(a), len(b)) return tuple([If(cond, ela, elb) for ela, elb in zip(a, b)]) if not hasattr(a, 'sexpr'): raise ValueError("Can not ite object of type {!r}".format(type(a))) return z3.If(cond, a, b)
def to_z3(p): """ Convert a sympy expression to Z3 expression >>> from sympy.abc import x,y,z >>> to_z3(x * 7.3 >= y) 73/10*x >= y >>> to_z3(7.3 >= z) z <= 73/10 """ if __debug__: assert isinstance(p, Expr) and p.is_Relational, p import z3 ss = map(str, get_vars(p)) if len(ss) >= 2: typ = "{} = z3.Reals('{}')" z3_vars_decl = typ.format(','.join(ss), ' '.join(ss)) else: typ = "{} = z3.Real('{}')" z3_vars_decl = typ.format(ss[0], ss[0]) exec(z3_vars_decl) f = eval(str(p)) if __debug__: assert z3.is_expr(f), f return f
def add_engine_object(self, elem): if z3.is_expr(elem): self._engine_objects[MUZ] = elem elif isinstance(elem, kanren.Var): self._engine_objects[KANREN_LOGPY] = elem else: raise Exception(f"unsupported Variable object: {type(elem)}")
def is_trans(f): """ Check if f has some pre variables Examples: >>> from z3 import * >>> x,y = Ints('x y') >>> is_trans(x) False >>> is_trans(x+y==10) False >>> is_trans(Implies(x==10,y==0)) False >>> is_trans(And(x==y,y==4)) False >>> is_trans(IntVal(3)) False >>> is_trans(3) Traceback (most recent call last): ... AssertionError: 3 """ if __debug__: assert is_expr(f), f return pre_kw in str(f)
def getConstraints(m, resultAsDict=False): """ Input a model m, returns its set of constraints in either 1) sage dict {x:7,y:10} 1) z3 expr [x==7,y==0] sage: S = z3.Solver() sage: S.add(z3.Int('x') + z3.Int('y') == z3.IntVal('7')) sage: S.check() sat sage: M = S.model() sage: d = getConstraints(M, resultAsDict=True) sage: sorted(d.items(), key=lambda(k,_): str(k)) [(x, 7), (y, 0)] sage: getConstraints(M) [y == 0, x == 7] sage: S.reset() """ assert m is not None, m if resultAsDict: #sage format rs = [(var(str(v())),sage_eval(str(m[v]))) for v in m] rs = dict(rs) assert all(is_sage_expr(x) for x in rs.keys()) assert all(is_sage_real(x) or is_sage_int(x) for x in rs.values()) else: #z3 format rs = [v()==m[v] for v in m] assert all(z3.is_expr(x) for x in rs) return rs
def getModels(cls, f, k): """ Returns the first k models satisfiying f. If f is not satisfiable, returns False. If f cannot be solved, returns None If f is satisfiable, returns the first k models If f is a tautology, i.e., True, then the result is [] """ assert z3.is_expr(f), f assert k >= 1, k solver = cls.createSolver() solver.add(f) models = [] i = 0 while solver.check() == z3.sat and i < k: i = i + 1 m = solver.model() if not m: #if m == [] break models.append(m) #create new constraint to block the current model block = z3.Not(z3.And([v() == m[v] for v in m])) solver.add(block) stat = solver.check() if stat == z3.unknown: rs = None elif stat == z3.unsat and i==0: rs = False else: rs = models return rs, stat
def sha3_(self, global_state): global keccak_function_manager state = global_state.mstate environment = global_state.environment op0, op1 = state.stack.pop(), state.stack.pop() try: index, length = util.get_concrete_int(op0), util.get_concrete_int(op1) # FIXME: broad exception catch except: # Can't access symbolic memory offsets if is_expr(op0): op0 = simplify(op0) state.stack.append(BitVec("KECCAC_mem[" + str(op0) + "]", 256)) return [global_state] try: state.mem_extend(index, length) data = b''.join([util.get_concrete_int(i).to_bytes(1, byteorder='big') for i in state.memory[index: index + length]]) except AttributeError: argument = str(state.memory[index]).replace(" ", "_") result = BitVec("KECCAC[{}]".format(argument), 256) keccak_function_manager.add_keccak(result, state.memory[index]) state.stack.append(result) return [global_state] keccak = utils.sha3(utils.bytearray_to_bytestr(data)) logging.debug("Computed SHA3 Hash: " + str(binascii.hexlify(keccak))) state.stack.append(BitVecVal(util.concrete_int_from_bytes(keccak, 0), 256)) return [global_state]
def entails(S, claim): """ Checking the validity of S => claim """ if __debug__: assert isinstance(S, Solver), S assert is_expr(claim), claim logger.debug('premise:\n{}\n'.format(S)) logger.debug('claim:\n{}\n'.format(claim)) # print 'entail' # print S # print claim S.push() S.add(Not(claim)) check_rs = S.check() if check_rs == sat: r = False, S.model() elif check_rs == unsat: r = True, None #unsat, no model elif check_rs == unknown: logger.warn('unknown for {}'.format(S)) r = unknown, None #unknown, error else: raise AssertionError('result: {} for\n{}'.format(check_rs, S)) S.pop() return r
def __init__(self, bdd, zbdd, idx): assert z3.is_expr(zbdd), zbdd assert idx >= 0, idx self.bdd = bdd self.zbdd = zbdd self.idx = idx
def get_literals(f): """ Obtain variables from a formula. Make calls to _get_literals(). """ assert is_expr(f), f return _get_literals(f, [])
def slice_defs(prop, defs, assumes_state, assumes_trans): """ Return a new (potentially empty) def dictionary from the old one consisting of only necessary variable definitions to prove property """ if __debug__: assert is_dict(defs), defs assert is_list(assumes_state), assumes_state assert is_list(assumes_trans), assumes_trans fs = [prop] + assumes_state + assumes_trans fs = [f for f in fs if is_expr(f)] vs = [get_vars(f) for f in fs] vs = [cur(v_) if is_pre(v_) else v_ for v_ in vflatten(vs)] vs = vset(vs, fhash) vs_ = [Prog.get_influence_vs(v, defs, []) for v in vs] vs = vset(vflatten(vs + vs_), fhash) a_defs = OrderedDict() for v in vs: k = fhash(v) if k in defs: a_defs[k] = defs[k] return a_defs
def main(self, a): if z3.is_expr(a): return self.pp_expr(a, 0, []) elif z3.is_sort(a): return self.pp_sort(a) elif z3.is_func_decl(a): return self.pp_name(a) elif isinstance(a, z3.Goal) or isinstance(a, z3.AstVector): return self.pp_seq(a, 0, []) elif isinstance(a, z3.Solver): return self.pp_seq(a.assertions(), 0, []) elif isinstance(a, z3.Fixedpoint): return a.sexpr() elif isinstance(a, z3.Optimize): return a.sexpr() elif isinstance(a, z3.ApplyResult): return self.pp_seq_seq(a, 0, []) elif isinstance(a, z3.ModelRef): return self.pp_model(a) elif isinstance(a, z3.FuncInterp): return self.pp_func_interp(a) elif isinstance(a, list) or isinstance(a, tuple): return self.pp_list(a) else: return to_format(self.pp_unknown())
def expr_set(fs): """ Return a set of formulas (i.e. all items are distinct) using hashing """ assert all(f is None or is_expr(f) for f in fs), fs return vset(fs, lambda f: None if f is None else fhash(f))
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 check_reentrancy_bug(memory, solver, path_condition: list = None): """This function is used to detect reentrancy vulnerabilities, Args: path_condition: current path condition memory: current memory of Wasm solver: current z3 solver """ list_solver = solver.units() for expr in list_solver: if not z3.is_expr(expr): continue vars = get_vars(expr) flag_empty = 0 for var in vars: if var in global_vars.dict_symbolic_address: flag_empty += 1 tmp_dict = global_vars.find_dict_root(var) if not tmp_dict: continue for item in tmp_dict: if item in global_vars.list_storageStore: continue else: global_vars.find_reentrancy_detection() if flag_empty == 0: global_vars.find_reentrancy_detection()
def __init__(self, cond, zcond, mdef): # assert isinstance(cond, pycudd.DdNode), cond assert z3.is_expr(zcond) assert mdef is None or isinstance(mdef, str), mdef #CONFIG_A, 'y', 'm' self.cond = cond self.zcond = zcond self.mdef = mdef
def retval(p): if p.is_symbol(): z3exp = (z3.Real if is_real else z3.Int)(str(p)) else: z3exp = (z3.RealVal if is_real else z3.IntVal)(str(p)) if __debug__: assert z3.is_expr(z3exp), z3exp return z3exp
def get_constraints(m, result_as_dict=False): """ Input a model m, returns its set of constraints in either 1) sage dict {x:7,y:10} 1) z3 expr [x==7,y==0] sage: S = z3.Solver() sage: S.add(z3.Int('x') + z3.Int('y') == z3.IntVal('7')) sage: S.check() sat sage: M = S.model() sage: d = SMT_Z3.get_constraints(M, result_as_dict=True) sage: sorted(d.items(), key=lambda(k,_): str(k)) [(x, 7), (y, 0)] sage: SMT_Z3.get_constraints(M) [y == 0, x == 7] sage: S.reset() """ assert m is not None, m if result_as_dict: #sage format rs = [(var(str(v())),sage_eval(str(m[v]))) for v in m] rs = dict(rs) if __debug__: assert all(is_sage_expr(x) for x in rs.keys()) assert all(is_sage_real(x) or is_sage_int(x) for x in rs.values()) else: #z3 format rs = [v()==m[v] for v in m] if __debug__: assert all(z3.is_expr(x) for x in rs) return rs
def to_z3exp(p, is_real): """ Convert a Sage expression to a Z3 expression Initially implements with a dictionary containing variables e.g. {x:Real('x')} but the code is longer and more complicated. This implemention does not require a dictionary pass in. Todo: cache this function """ assert is_sage_expr(p), p def retval(p): if p.is_symbol(): z3exp = (z3.Real if is_real else z3.Int)(str(p)) else: z3exp = (z3.RealVal if is_real else z3.IntVal)(str(p)) if __debug__: assert z3.is_expr(z3exp), z3exp return z3exp try: oprs = p.operands() except Exception: return retval(p) if is_empty(oprs): return retval(p) else: oprs = [SMT_Z3.to_z3exp(o, is_real) for o in oprs] z3exp = SMT_Z3._reduce(p.operator(),oprs) assert z3.is_expr(z3exp), z3exp return z3exp
def _op_raw_Concat(*args): sz = len(args) ctx = None for a in args: if z3.is_expr(a): ctx = a.ctx break # TODO: I don't think this is needed for us, we don't deal with Seq or Regex # if z3.is_seq(args[0]) or isinstance(args[0], str): # v = (z3.Ast * sz)() # for i in range(sz): # v[i] = args[i].as_ast() # return z3.SeqRef(z3.Z3_mk_seq_concat(ctx.ref(), sz, v), ctx) # # if z3.is_re(args[0]): # v = (z3.Ast * sz)() # for i in range(sz): # v[i] = args[i].as_ast() # return z3.ReRef(z3.Z3_mk_re_concat(ctx.ref(), sz, v), ctx) r = args[0] for i in range(sz - 1): r = z3.BitVecRef(z3.Z3_mk_concat(ctx.ref(), r.as_ast(), args[i + 1].as_ast()), ctx) return r
def simplify(self, expr, **kwargs): if(z3.is_expr(expr)): return z3.simplify(expr, **kwargs) else: # assume that expr has already been 'simplified' to a constant. return 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
def _reduce(op, ls): """ Apply operator op to the list ls of arguments. The arguments must be of type that z3 exprs. In other words, cannot use Sage's datatype (e.g. 7==Real('x') gives False which is not expected) (+,*) work on 2+ arguments (pow,==,!=,>=,>,<=,<) work on 2 arguments Note, it seems the above arguments are *enough*, no need to implement for (-,div) etc because the function that calls this will break x - y to _reduce(op,[x,-y]) or x / y to _reduce(op,[x,1/y]) and 1/y => mul(1,y^{-1}) sage: SMT_Z3._reduce(operator.add,[z3.Real('x'),z3.RealVal(3)]) x + 3 sage: SMT_Z3._reduce(operator.add,[z3.Real('x'),z3.RealVal(3),z3.Real('y')]) x + 3 + y sage: SMT_Z3._reduce(operator.mul,[z3.Real('x'),z3.RealVal('3'),z3.Real('y')]) x*3*y sage: SMT_Z3._reduce(operator.pow,[z3.Real('x'),z3.RealVal(3)]) x**3 sage: SMT_Z3._reduce(operator.pow,[z3.RealVal(3),z3.Real('x')]) 3**x sage: SMT_Z3._reduce(operator.pow,[z3.Real('x'),z3.RealVal(3.3)]) x**(33/10) sage: SMT_Z3._reduce(operator.pow,[z3.Real('x'),z3.Real('x')]) x**x #1/x sage: SMT_Z3._reduce(operator.pow,[z3.Real('x'),z3.IntVal('-1')]) x**ToReal(-1) sage: SMT_Z3._reduce(operator.pow,[z3.Int('x'),z3.IntVal('-1')]) x**-1 sage: SMT_Z3._reduce(operator.pow,[z3.IntVal('-7'),z3.IntVal('-1')]) -7**-1 sage: SMT_Z3._reduce(operator.mul,[z3.IntVal('-7'),z3.IntVal('-1')]) -7*-1 sage: SMT_Z3._reduce(operator.mul,[z3.RealVal('-7'),z3.RealVal('-1')]) -7*-1 sage: SMT_Z3._reduce(operator.mul,[z3.RealVal('-7'),z3.RealVal('-9')]) -7*-9 sage: SMT_Z3._reduce(operator.mul,[z3.RealVal('-7'),z3.IntVal('-9')]) -7*ToReal(-9) sage: SMT_Z3._reduce(operator.mul,[z3.RealVal(-7),z3.IntVal('-9')]) -7*ToReal(-9) sage: SMT_Z3._reduce(operator.eq,[z3.RealVal(-7),z3.Real('x')]) -7 == x sage: SMT_Z3._reduce(operator.eq,[z3.RealVal(-7),z3.Real('x')]) -7 == x sage: SMT_Z3._reduce(operator.eq,[z3.RealVal('-7'),z3.Real('x')]) -7 == x sage: SMT_Z3._reduce(operator.eq,[z3.IntVal('-7'),z3.Real('x')]) ToReal(-7) == x sage: SMT_Z3._reduce(operator.eq,[z3.IntVal('-7'),z3.Int('x')]) -7 == x sage: SMT_Z3._reduce(operator.div,[z3.IntVal('-7'),z3.Int('x')]) Traceback (most recent call last): ... AssertionError: unknown op: <built-in function div> """ if __debug__: assert all(z3.is_expr(f) for f in ls) if op == operator.add: if __debug__: assert len(ls) >= 2 return reduce(lambda a, b: a+b, ls[1:], ls[0]) elif op == operator.mul: if __debug__: assert len(ls) >= 2 return reduce(lambda a, b: a*b, ls[1:], ls[0]) elif op == operator.pow: if __debug__: assert len(ls) == 2 return ls[0]**ls[1] elif op == operator.eq: if __debug__: assert len(ls) == 2 return ls[0] == ls[1] elif op == operator.ne: if __debug__: assert len(ls) == 2 return ls[0] != ls[1] elif op == operator.ge: if __debug__: assert len(ls) == 2 return ls[0] >= ls[1] elif op == operator.gt: if __debug__: assert len(ls) == 2 return ls[0] > ls[1] elif op == operator.le: if __debug__: assert len(ls) == 2 return ls[0] <= ls[1] elif op == operator.lt: if __debug__: assert len(ls) == 2 return ls[0] < ls[1] else: raise AssertionError('unknown op: {}'.format(op))
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): 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
def exp_int(x): """ sage: SMT_Z3.exp_int(x>10) x > 10 """ return x if z3.is_expr(x) else SMT_Z3.to_z3exp(x,is_real=False)
def exp_real(x): return x if z3.is_expr(x) else SMT_Z3.to_z3exp(x,is_real=True)