def bvsub_safe(x, y, signed=False): """BitVector subtraction overflow/underflow checks Parameters ---------- x,y : z3.BitVecRef or z3.BitVecNumRef These variables are the two BitVecs that will be subtracted. signed : bool, optional Should this subtraction be treated as signed? Returns ------- tuple tuple of z3 solver constraints to detect an overflow or underflow This function wraps Z3 C API functions to allow for a python interpretation of overflow and underflow checks. The returned tuple does not perform the subtraction, rather it is constraints that will perform the checks for overflow and underflow. Example ------- If you want to verify the subtraction of x and y will not overflow/underflow:: In [1]: import z3 In [2]: import pyState.z3Helpers In [3]: s = z3.Solver() In [4]: x,y,z = z3.BitVecs('x y z',32) In [5]: s.add(pyState.z3Helpers.bvsub_safe(x,y)) In [6]: s.add(x - y == z) In [7]: s Out[7]: [If(y == 1 << 31, x < 0, Implies(And(0 < x, 0 < -y), 0 < x + -y)), ULE(y, x), x - y == z] In [8]: s.check() Out[8]: sat """ assert x.ctx_ref() == y.ctx_ref() a, b = z3._coerce_exprs(x, y) return (z3.BoolRef( z3.Z3_mk_bvsub_no_overflow(a.ctx_ref(), a.as_ast(), b.as_ast())), z3.BoolRef( z3.Z3_mk_bvsub_no_underflow(a.ctx_ref(), a.as_ast(), b.as_ast(), signed)))
def _Add_cstr(x, y): assert x.ctx_ref() == y.ctx_ref() a, b = _coerce_exprs(x, y) over_flow = z3.BoolRef(z3.Z3_mk_bvadd_no_overflow(x.ctx_ref(), x.as_ast(), y.as_ast(), True)) print (over_flow) return over_flow
def bvmul_no_overflow(a, b, signed): if a.size() != b.size(): raise Exception( 'Sizes do not match for overfow check: {} != {}'.format(a.size(), b.size())) assert a.ctx_ref() == b.ctx_ref() a, b = _coerce_exprs(a, b) return z3.BoolRef(z3.Z3_mk_bvmul_no_overflow(a.ctx_ref(), a.as_ast(), b.as_ast(), signed))
def eq(self, conv, other): # Problems: Z3 catches fire if we apply __eq__ to something of tuple # sort, because apparently we contain DatatypeRef's, not ExprRef's. # Therefore, we have to use our own eq facility. eq = z3.Z3_mk_eq(conv.ctx.ctx, self.ast.ast, other.ast.ast) ref = z3.BoolRef(eq, conv.ctx) new_ast = Z3ast(ref, self.conv, self.conv.bool_sort) self.conv.store_ast(new_ast) return new_ast
def convert(self, formula): z3term = self.walk(formula) if formula.node_type in op.QUANTIFIERS: return z3.QuantifierRef(z3term, self.ctx) elif formula.node_type() in BOOLREF_SET: return z3.BoolRef(z3term, self.ctx) elif formula.node_type() in ARITHREF_SET: return z3.ArithRef(z3term, self.ctx) elif formula.node_type() in BITVECREF_SET: return z3.BitVecRef(z3term, self.ctx) elif formula.is_symbol() or formula.is_function_application(): if formula.is_function_application(): type_ = formula.function_name().symbol_type() type_ = type_.return_type else: type_ = formula.symbol_type() if type_.is_bool_type(): return z3.BoolRef(z3term, self.ctx) elif type_.is_real_type() or type_.is_int_type(): return z3.ArithRef(z3term, self.ctx) elif type_.is_array_type(): return z3.ArrayRef(z3term, self.ctx) elif type_.is_bv_type(): return z3.BitVecRef(z3term, self.ctx) else: raise NotImplementedError(formula) elif formula.node_type() in op.ARRAY_OPERATORS: return z3.ArrayRef(z3term, self.ctx) else: assert formula.is_constant(), formula type_ = formula.constant_type() if type_.is_bool_type(): return z3.BoolRef(z3term, self.ctx) elif type_.is_real_type() or type_.is_int_type(): return z3.ArithRef(z3term, self.ctx) elif type_.is_array_type(): return z3.ArrayRef(z3term, self.ctx) elif type_.is_bv_type(): return z3.BitVecRef(z3term, self.ctx) else: raise NotImplementedError(formula)
def bvdiv_safe(x, y, signed=False): """BitVector division overflow check Parameters ---------- x,y : z3.BitVecRef or z3.BitVecNumRef These variables are the two BitVecs that will be divided signed : bool, optional Should this division be treated as signed? Returns ------- tuple tuple of z3 solver constraints to detect an overflow This function wraps Z3 C API functions to allow for a python interpretation of overflow checks. The returned tuple does not perform the division, rather it is constraints that will perform the checks for overflow. Example ------- If you want to verify the division of x and y will not overflow:: In [1]: import z3 In [2]: import pyState.z3Helpers In [3]: s = z3.Solver() In [4]: x,y,z = z3.BitVecs('x y z',32) In [5]: s.add(pyState.z3Helpers.bvdiv_safe(x,y)) In [6]: s.add(x / y == z) In [7]: s Out[7]: [Not(And(x == 1 << 31, y == 4294967295)), x/y == z] In [8]: s.check() Out[8]: sat """ assert x.ctx_ref() == y.ctx_ref() a, b = z3._coerce_exprs(x, y) return z3.BoolRef( z3.Z3_mk_bvsdiv_no_overflow(a.ctx_ref(), a.as_ast(), b.as_ast()))
def isInt(x): """Wraps Z3 C API to perform isInt check on Real object x Parameters ---------- x : z3.ArithRef or z3.RatNumRef Real variable from calls like z3.Real('x') Returns ------- z3.BoolRef z3.BoolRef asserting type x is Int (i.e.: ends in .0) This function wraps Z3 C API functions to allow for a python interpretation of isInt. The returned value is a boolean that the input Real type x is an integer (i.e.: ends in .0). This call is the C API that performs the check at solve time, rather than entry time. Example ------- If you want to verify that Real type x is an Int:: In [1]: import z3 In [2]: from pySym import pyState.z3Helpers In [3]: s = z3.Solver() In [4]: x = z3.Real('x') In [5]: s.add(pyState.z3Helpers.isInt(x)) In [6]: s.add(x == 5.0) In [7]: s Out[7]: [IsInt(x), x == 5] In [8]: s.check() Out[8]: sat """ return z3.BoolRef(z3.Z3_mk_is_int(x.ctx_ref(),x.as_ast()))
def my_eq(x, y): ctx = z3.main_ctx() return z3.BoolRef(z3.Z3_mk_eq(ctx.ref(), x.as_ast(), y.as_ast()), ctx)
def my_and(*args): ctx = z3.main_ctx() _args, sz = z3._to_ast_array(args) return z3.BoolRef(z3.Z3_mk_and(ctx.ref(), sz, _args), ctx)
def my_eq(x, y): ctx = z3.main_ctx() # print "my_eq: {} = {}".format(x,y) return z3.BoolRef(z3.Z3_mk_eq(ctx.ref(), x.as_ast(), y.as_ast()), ctx)
def _make_pb(self, op, props, k, name): args, coeffs, sz = as_z3_ast_array_coeffs(props, self._ctx) v = z3.BoolRef(op(self._ctx.ref(), sz, args, coeffs, k), self._ctx) r = self.new_var(name).val self._solver.add(self._make_fast_eq(r, v)) return Z3BoolRef(r)
def _make_fast_eq(self, x, y): return z3.BoolRef(z3.Z3_mk_eq(self._ctx.ref(), x.as_ast(), y.as_ast()), self._ctx)
def __neg__(self): v = self.val ctx = v.ctx return Z3BoolRef(z3.BoolRef(z3.Z3_mk_not(ctx.ref(), v.as_ast()), ctx))
def z3_reduce(op, props, ctx): args, sz = as_z3_ast_array(props, ctx) return Z3BoolRef(z3.BoolRef(op(ctx.ref(), sz, args), ctx))
def Eq(arg1, arg2): if arg2 is None: return False a, b = z3._coerce_exprs(arg1, arg2) return z3.BoolRef(z3.Z3_mk_eq(arg1.ctx_ref(), a.as_ast(), b.as_ast()), arg1.ctx)