def write(self, addr, data): if isinstance(addr, int): return self.write_con(addr, data) elif z3.is_bv_value(addr): return self.write_con(addr.as_long(), data) addr = z3.simplify(addr) if z3.is_bv_value(addr): return self.write_con(addr.as_long(), data) addrs = self.eval_max(addr, self.max_eval) if addrs == []: raise ESILUnsatException("Unsat symbolic address") elif len(addrs) == 1: # should I add this constraint? no? return self.write_con(addrs[0].as_long(), data) # constrain it to be one of these self.solver.add(z3.Or(*[addr == a for a in addrs])) data = self.data_to_bv(data) length = data.size() // 8 for address in addrs: addrint = address.as_long() val = self.pack_bv(self.cond_read(addrint, length)) self.write_con(addrint, z3.If(addr == address, data, val))
def check_addr(self, bv, mode="r", length=None, data=None): if isinstance(bv, int): return elif z3.is_bv_value(bv): return bv = z3.simplify(bv) if z3.is_bv_value(bv): return elif z3.is_bv(bv): mode_to_event = { "r": ESILSolveEvent.SymRead, "w": ESILSolveEvent.SymWrite, "x": ESILSolveEvent.SymExec, "f": ESILSolveEvent.SymFree } event = mode_to_event[mode] if event in self.events: # normalize everything to be bvs if isinstance(length, int): length = BV(length, self.bits) if isinstance(data, list): data = self.memory.pack_bv(data) ctx = EventContext(bv, length, data) for hook in self.events[event]: hook(self, ctx)
def read_bv(self, addr, length): if isinstance(addr, int): return self.pack_bv(self.cond_read(addr, length)) elif z3.is_bv_value(addr): return self.pack_bv(self.cond_read(addr.as_long(), length)) addr = z3.simplify(addr) if z3.is_bv_value(addr): return self.pack_bv(self.cond_read(addr.as_long(), length)) addrs = self.eval_max(addr, self.max_eval) if addrs == []: raise ESILUnsatException("Unsat symbolic address") elif len(addrs) == 1: # should I add this constraint? no? return self.pack_bv(self.cond_read(addrs[0].as_long(), length)) # constrain it to be one of these self.solver.add(z3.Or(*[addr == a for a in addrs])) result = None for address in addrs: val = self.pack_bv(self.cond_read(address.as_long(), length)) if result == None: result = val else: result = z3.If(addr == address, val, result) return z3.simplify(result)
def get_lazy_pcs(self, pc): arg1 = z3.simplify(pc.arg(1)) arg2 = z3.simplify(pc.arg(2)) if z3.is_bv_value(arg1) and z3.is_bv_value(arg2): return [arg1.as_long(), arg2.as_long()] else: return []
def read(self, addr, length): if isinstance(addr, int): return self.cond_read(addr, length) elif z3.is_bv_value(addr): return self.cond_read(addr.as_long(), length) addr = z3.simplify(addr) if z3.is_bv_value(addr): return self.cond_read(addr.as_long(), length) data = self.read_bv(addr, length) return self.unpack_bv(data, int(data.size() / 8))
def add_engine_object(self, elem): if z3.is_bv_value(elem): self._engine_objects[MUZ] = elem elif isinstance(elem, str): self._engine_objects[KANREN_LOGPY] = elem else: raise Exception(f"unsupported Constant object {type(elem)}")
def do_PICK(op, stack, state): n, = pop_values(stack, state) if z3.is_bv_value(n): n = n.as_long() # esil from pcode is 1, not 0 indexed for PICK stack.append(stack[-n])
def prepare(val, signext=False, size=SIZE) -> z3.BitVecRef: if z3.is_bv(val): szdiff = size - val.size() if szdiff > 0: if signext: result = z3.SignExt(szdiff, val) else: result = z3.ZeroExt(szdiff, val) elif szdiff < 0: result = z3.Extract(size - 1, 0, val) else: result = val elif type(val) == int: result = z3.BitVecVal(val, size) elif z3.is_int(val): result = z3.Int2BV(val, size) elif z3.is_fp(val): # changing up this logic to align with r2ghidra impl result = z3.fpToIEEEBV(val) #result = val else: result = z3.BitVecVal(val, size) if not z3.is_bv_value(result): return z3.simplify(result) else: return result
def compare(self, s1, s2, length=None): max_len = self.max_len if length != None: length = z3.simplify(length) if z3.is_bv_value(length): max_len = length.as_long() else: # no len use null len1, last1 = self.search(s1, [BZERO]) len2, last2 = self.search(s2, [BZERO]) max_len = min(last1, last2) + 1 length = z3.If(len1 < len2, len1, len2) + 1 ret_val = ZERO for i in range(max_len): c1 = z3.ZeroExt(24, self.read_bv(s1 + i, 1)) c2 = z3.ZeroExt(24, self.read_bv(s2 + i, 1)) new_ind = z3.BitVecVal(i, SIZE) over_len = self.solver.check(length > new_ind) == z3.unsat if not over_len: this_val = z3.If(c1 == c2, ZERO, z3.If(c1 < c2, NEGONE, ONE)) new_val = z3.If(ret_val == ZERO, this_val, ret_val) ret_val = z3.If(length > new_ind, new_val, ret_val) else: break return z3.simplify(ret_val)
def bv_to_int(self, bv): bv = z3.simplify(bv) if z3.is_bv_value(bv): return bv.as_long() # this is terrible and temporary elif z3.is_bv(bv): print("symbolic addr: %s" % bv) self.hit_symbolic_addr = True sat = self.solver.check() if sat == z3.sat: model = self.solver.model() try: val = model.eval(bv, model_completion=True).as_long() #print(val) '''if self.multi_concretize: self.solver.push() self.solver.add(bv != val) vals = solver.EvalMax(self.solver, bv) if len(vals) > 0: self.concrete_addrs.append({"bv": bv, "values": vals}) self.solver.pop()''' self.solver.add(bv == val) return val except: # idk man i need a default value in case # there are no constraints on the addr self.solver.add(bv == self.default_addr) return self.default_addr else: raise ESILUnsatException("no sat symbolic address found")
def prepare(val, signext=False, size=SIZE) -> z3.BitVecRef: if z3.is_bv(val): szdiff = size-val.size() if szdiff == 0: result = val elif szdiff > 0: if signext: result = z3.SignExt(szdiff, val) else: result = z3.ZeroExt(szdiff, val) elif szdiff < 0: result = z3.Extract(size-1, 0, val) elif isinstance(val, int): result = z3.BitVecVal(val, size) elif z3.is_int(val): result = z3.Int2BV(val, size) elif z3.is_fp(val): result = z3.fpToIEEEBV(val) else: result = z3.BitVecVal(val, size) if not z3.is_bv_value(result): return z3.simplify(result) else: return result
def collect_numerals(z3term): if z3.is_int_value(z3term) or z3.is_bv_value(z3term): yield z3term elif z3.is_app_of(z3term, z3.Z3_OP_ITE): for z in collect_numerals(z3term.arg(1)): yield z for z in collect_numerals(z3term.arg(2)): yield z
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 do_U2D(op, stack, state): val, = pop_values(stack, state) if z3.is_bv_value(val): fp = z3.FPVal(val.as_long(), FSIZE) else: fp = z3.fpUnsignedToFP(FPM, val, FSIZE) stack.append(fp)
def addr_to_int(self, bv): if z3.is_bv_value(bv): return bv.as_long() bv = z3.simplify(bv) if z3.is_bv_value(bv): return bv.as_long() else: # should be only for free() now if self.solver.check() == z3.sat: model = self.solver.model() val = model.eval(bv, model_completion=True) self.solver.add(bv == val) return val.as_long() else: raise ESILUnsatException( f"no sat symbolic address found for: {bv}")
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 search(self, addr, needle, length=None, reverse=False): max_len = self.max_len n = len(needle) if n == 0: return ZERO if length != None: nbv = z3.BitVecVal(n - 1, SIZE) length = z3.simplify(length - nbv) if z3.is_bv_value(length): max_len = length.as_long() else: length = z3.BitVecVal(max_len - n + 1, SIZE) ret_ind = self.error # hmm idk ind_con = z3.BoolVal(False) rargs = (0, max_len, 1) if reverse: rargs = (max_len, 0, -1) for i in range(*rargs): cs = self.read(addr + i, n) found = all([(self.solver.check(cs[k] != needle[k]) == z3.unsat) for k in range(n)]) # oof not_found = any([ (self.solver.check(cs[k] == needle[k]) == z3.unsat) for k in range(n) ]) new_ind = z3.BitVecVal(i, SIZE) over_len = self.solver.check(length > new_ind) == z3.unsat if not over_len: if found: ind_con = z3.And(length > new_ind, z3.Not(ind_con)) ret_ind = z3.If(ind_con, new_ind, ret_ind) return z3.simplify(ret_ind), i elif not not_found: new_cons = [cs[k] == needle[k] for k in range(n)] new_cons.append(length > new_ind) new_con = z3.And(*new_cons) ind_con = z3.And(new_con, z3.Not(ind_con)) ret_ind = z3.If(ind_con, new_ind, ret_ind) else: if not reverse: return z3.simplify(ret_ind), i return z3.simplify(ret_ind), max_len
def do_I2F(op, stack, state): val, = pop_values(stack, state) if z3.is_bv_value(val): fp = z3.FPVal(val.as_long(), FSIZE) else: fp = z3.FP("fp%d" % float_data["count"], FSIZE) state.solver.add(z3.fpToUBV(FPM, fp, z3.BitVecSort(SIZE)) == val) float_data["count"] += 1 stack.append(fp)
def cond_read(self, addr, length): if isinstance(length, int): return self.read_con(addr, length) elif z3.is_bv_value(length): return self.read_con(addr, length.as_long()) length = z3.simplify(length) if z3.is_bv_value(length): return self.read_con(addr, length.as_long()) else: data = [] for i in range(self.max_len): sc = self.read_con_bv(addr + i, 1) new_len = z3.BitVecVal(i, SIZE) over_len = self.solver.check(length > new_len) == z3.unsat if not over_len: data.append(sc) else: break return data
def read(state, fd, addr, length): fd = state.evalcon(fd).as_long() #length = state.evalcon(length).as_long() length = z3.simplify(length) if z3.is_bv_value(length): rlen = length.as_long() else: rlen = len(state.mem_read(addr, length)) # hax data = state.fs.read(fd, rlen) dlen = BV(len(data)) state.mem_copy(addr, data, length) return z3.If(dlen < length, dlen, length)
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 do_if(self, state): val, = esilops.pop_values(state.stack, state) val = z3.simplify(val) zero = 0 if z3.is_bv_value(val): val = val.as_long() elif z3.is_bv(val): zero = z3.BitVecVal(0, val.size()) if state.condition == None: if type(val) == int: return val != zero else: return self.eq(val != zero) else: return z3.And(self.eq(val != zero), state.condition)
def copy(self, dst, data, length): length = z3.simplify(length) if z3.is_bv_value(length): self.write(dst, data[:length.as_long()]) else: new_data = [] for i in range(len(data)): sc = data[i] dc = self.read_bv(dst + i, 1) new_len = z3.BitVecVal(i, SIZE) over_len = self.solver.check(length > new_len) == z3.unsat if not over_len: new_data.append(z3.If(length > new_len, sc, dc)) else: break self.write(dst, new_data)
def bv_to_int(self, bv): bv = z3.simplify(bv) if z3.is_bv_value(bv): return bv.as_long() # this is terrible and temporary elif z3.is_bv(bv): #print("symbolic addr: %s" % bv) self.hit_symbolic_addr = True if self.solver.check() == z3.sat: model = self.solver.model() val = model.eval(bv, model_completion=True) self.solver.add(bv == val) return val.as_long() else: raise ESILUnsatException("no sat symbolic address found")
def memcopy(self, dst, src, length): length = z3.simplify(length) if z3.is_bv_value(length): data = self.read(src, length.as_long()) self.write(dst, data) else: data = [] for i in range(self.max_len): sc = self.read_bv(src + i, 1) dc = self.read_bv(dst + i, 1) new_len = z3.BitVecVal(i, SIZE) over_len = self.solver.check(length > new_len) == z3.unsat if not over_len: data.append(z3.If(length > new_len, sc, dc)) else: break self.write(dst, data)
def add(self, state: ESILState): """ Add state to the manager :param state: The state to be added """ pc = state.registers["PC"] if z3.is_bv_value(pc): if pc.as_long() in self.avoid: self.inactive.add(state) else: self.active.add(state) elif self.lazy or state.is_sat(): self.active.add(state) else: self.unsat.add(state)
def overlay(self, chunk, base_off, chunk_off, length): slen = z3.simplify(length) if z3.is_bv_value(slen): for i in range(slen.as_long()): if isinstance(chunk, Memory): sel = chunk.select(chunk_off + i) else: sel = z3.Select(chunk, chunk_off + i) self._mem = z3.Store(self._mem, base_off + i, sel) else: if self._idx is None: self._idx = z3.BitVec('idx', 256) if isinstance(chunk, Memory): chunk_val = chunk.select(self._idx - base_off + chunk_off) else: chunk_val = z3.Select(chunk, self._idx - base_off + chunk_off) self._mem = z3.If( z3.And(self._idx >= base_off, self._idx < base_off + length), z3.Store(state.MemoryEmpty, self._idx, chunk_val), self._mem)
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_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_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 atoi_helper(state, addr, size=SIZE): # still sucks string, length = state.symbolic_string(addr) if z3.is_bv_value(string): cstr = state.evaluate_string(string) return BV(int(cstr), size) else: length = state.evalcon(length).as_long() # unfortunate result = BV(0, size) is_neg = z3.BoolVal(False) m = BV(ord("-"), 8) for i in range(length): d = state.mem_read_bv(addr + i, 1) is_neg = z3.If(d == m, z3.BoolVal(True), is_neg) c = z3.If(d == m, BV(0, size), z3.ZeroExt(size - 8, d - BV_0)) result = result + (c * BV(10**(length - (i + 1)), size)) result = z3.If(is_neg, -result, result) return result
def memset(state, dst, ch, num): c = z3.Extract(7, 0, ch) # TODO big endian length = z3.simplify(num) if z3.is_bv_value(length): state.mem_write(dst, [c] * length.as_long()) else: data = [] for i in range(state.max_len): dc = state.read_bv(dst + i, 1) new_len = BV(i, SIZE) over_len = state.solver.check(length > new_len) == z3.unsat if not over_len: data.append(z3.If(length > new_len, c, dc)) else: break state.mem_write(dst, data) return dst
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 alloc(self, length=0x80): """ The dumbest memory allocation function known to human or alien life >>> state.memory.alloc(0x100) 0x02000100 """ if not self.heap_init: self.init_heap() needs = 0 if type(length) == int: needs = int(length / self.heap_bin) + 1 elif z3.is_bv_value(length): needs = int(length.as_long() / self.heap_bin) + 1 else: more = True while more: needs += 1 cur = z3.BitVecVal(needs * self.heap_bin, SIZE) more = (self.solver.check(length > cur) == z3.sat) slot = 0 avail = False while not avail: unused = [(slot + i) not in self.heap for i in range(needs)] avail = all(unused) if not avail: slot += unused[::-1].index(False) + 1 else: new_slots = [(slot + i, slot) for i in range(needs)] self.heap.update(dict(new_slots)) addr = self.heap_start + slot * self.heap_bin return addr
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 collect_numerals(z3term): if z3.is_int_value(z3term) or z3.is_bv_value(z3term): yield z3term elif z3.is_app_of(z3term, z3.Z3_OP_ITE): yield collect_numerals(z3term.arg(1)) yield collect_numerals(z3term.arg(2))
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 _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