Skip to content

Commit f3ee43e

Browse files
committed
Fix div_xy_y(): resolving word as_z3
1 parent 283b97f commit f3ee43e

3 files changed

Lines changed: 36 additions & 17 deletions

File tree

20.5 KB
Binary file not shown.

src/halmos/sevm.py

Lines changed: 19 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -2105,35 +2105,37 @@ def __init__(self, options: HalmosConfig, fun_info: FunctionInfo) -> None:
21052105
def div_xy_y(self, w1: Word, w2: Word, signed: bool = False) -> Word:
21062106
# return the number of bits required to represent the given value. default = 256
21072107
def bitsize(w: Word) -> int:
2108+
z3w = w.as_z3() if hasattr(w, "as_z3") else w
21082109
if (
2109-
w.decl().name() == "concat"
2110-
and is_bv_value(w.arg(0))
2111-
and int(str(w.arg(0))) == 0
2110+
z3w.decl().name() == "concat"
2111+
and is_bv_value(z3w.arg(0))
2112+
and int(str(z3w.arg(0))) == 0
21122113
):
2113-
return 256 - w.arg(0).size()
2114+
return 256 - z3w.arg(0).size()
21142115
return 256
21152116

2116-
w1 = normalize(w1)
2117+
w1_z3 = w1.as_z3() if hasattr(w1, "as_z3") else w1
2118+
w2_z3 = w2.as_z3() if hasattr(w2, "as_z3") else w2
21172119

2118-
if w1.decl().name() == "bvmul" and w1.num_args() == 2:
2119-
x = w1.arg(0)
2120-
y = w1.arg(1)
2121-
if eq(w2, x) or eq(w2, y): # xy/x or xy/y
2120+
if w1_z3.decl().name() == "bvmul" and w1_z3.num_args() == 2:
2121+
x = w1_z3.arg(0)
2122+
y = w1_z3.arg(1)
2123+
if eq(w2_z3, x) or eq(w2_z3, y): # xy/x or xy/y
21222124
if signed:
21232125
# Signed division: safe to simplify if divisor exactly matches factor
2124-
if eq(w2, x):
2125-
return y
2126-
elif eq(w2, y):
2127-
return x
2126+
if eq(w2_z3, x):
2127+
return BV(y, w1.size) # wrap back
2128+
elif eq(w2_z3, y):
2129+
return BV(x, w1.size)
21282130
else:
21292131
# Unsigned division: check for overflow
21302132
size_x = bitsize(x)
21312133
size_y = bitsize(y)
21322134
if size_x + size_y <= 256:
2133-
if eq(w2, x): # xy/x == y
2134-
return y
2135+
if eq(w2_z3, x): # xy/x == y
2136+
return BV(y, w1.size) # wrap back
21352137
else: # xy/y == x
2136-
return x
2138+
return BV(x, w1.size)
21372139
return None
21382140

21392141
def mk_div(self, ex: Exec, x: Any, y: Any) -> Any:
@@ -2178,7 +2180,7 @@ def arith(self, ex: Exec, op: int, w1: Word, w2: Word) -> Word:
21782180
return term
21792181

21802182
if op == OP_SDIV:
2181-
# Try signed simplification
2183+
# Try signed simplification first
21822184
simplified_sdiv = self.div_xy_y(w1, w2, signed=True)
21832185
if simplified_sdiv is not None:
21842186
return simplified_sdiv

tests/regression/foundry.lock

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
{
2+
"../lib/forge-std": {
3+
"rev": "1eea5bae12ae557d589f9f0f0edae2faa47cb262"
4+
},
5+
"../lib/halmos-cheatcodes": {
6+
"rev": "6da4e692c357ba6d641a2e677a28298cac9f76ab"
7+
},
8+
"../lib/openzeppelin-contracts": {
9+
"rev": "dbb6104ce834628e473d2173bbc9d47f81a9eec3"
10+
},
11+
"../lib/solady": {
12+
"rev": "4d4a7572ad01e84e96370e42bd10d1cc16c1fb65"
13+
},
14+
"../lib/solmate": {
15+
"rev": "bfc9c25865a274a7827fea5abf6e4fb64fc64e6c"
16+
}
17+
}

0 commit comments

Comments
 (0)