I found this post that gives a way of checking for overflow in solutions when adding bitVecs z3 bitvector overflow checking from python?
However, it only works when only adding 2 bitVecs, is there any way of extending it so it works for adding an arbitrary number of bitVecs? As far as I can tell, the problem is that "z3._coerce_exprs(x, y)" in
def bvadd_no_overflow(x, y, signed=False):
assert x.ctx_ref()==y.ctx_ref()
a, b = z3._coerce_exprs(x, y)
return BoolRef(Z3_mk_bvadd_no_overflow(a.ctx_ref(), a.as_ast(),
b.as_ast(), signed))
Only can take 2 inputs.
You can program this yourself, on top of the 2-place predicate z3 provides:
from z3 import *
def addition_does_not_overflow(xs, signed):
sofar = 0
noOverflow = True
for x in xs:
noOverflow = And(noOverflow, BVAddNoOverflow(x, sofar, signed))
sofar += x
return noOverflow
xs = [BitVec('x' + str(i), 2) for i in range(5)]
s = Solver()
s.add(addition_does_not_overflow(xs, False))
if s.check() == sat:
print(s.model())
else:
print("No solution")
This prints:
[x3 = 1, x2 = 2, x1 = 0, x4 = 0, x0 = 0]
and indeed, those numbers don't overflow when added as unsigned 2-bit vectors, i.e., those that range from 0
to 3
. Note that second argument of the predicate: You should pass True
if you want signed-arithmetic, and False
if otherwise.