Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Two simplifications that will be needed to deal with @zoep's issues regarding initcode equivalence #655

Merged
merged 15 commits into from
Feb 18, 2025
2 changes: 2 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,8 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
- Multiple solutions are allowed for a single symbolic expression
- Aliasing works much better for symbolic and concrete addresses
- Constant propagation for symbolic values
- One more simplification rule for `ReadByte` when the `CopySlice` after it
is writing after the position being read, so the `CopySlice` can be ignored

## Fixed
- We now try to simplify expressions fully before trying to cast them to a concrete value
Expand Down
6 changes: 6 additions & 0 deletions src/EVM/Expr.hs
Original file line number Diff line number Diff line change
Expand Up @@ -243,6 +243,9 @@ readByte i@(Lit x) (WriteWord (Lit idx) val src)
(Lit _) -> indexWord (Lit $ x - idx) val
_ -> IndexWord (Lit $ x - idx) val
else readByte i src
-- reading a byte that is lower than the dstOffset of a CopySlice, so it's just reading from dst
readByte i@(Lit x) (CopySlice _ (Lit dstOffset) _ _ dst) | dstOffset > x =
readByte i dst
readByte i@(Lit x) (CopySlice (Lit srcOffset) (Lit dstOffset) (Lit size) src dst)
= if x - dstOffset < size
then readByte (Lit $ x - (dstOffset - srcOffset)) src
Expand Down Expand Up @@ -279,6 +282,9 @@ readWord idx b@(WriteWord idx' val buf)
-- we do not have enough information to statically determine whether or not
-- the region we want to read overlaps the WriteWord
_ -> readWordFromBytes idx b
-- reading a Word that is lower than the dstOffset-32 of a CopySlice, so it's just reading from dst
readWord i@(Lit x) (CopySlice _ (Lit dstOffset) _ _ dst) | dstOffset > x+32 =
readWord i dst
readWord (Lit idx) b@(CopySlice (Lit srcOff) (Lit dstOff) (Lit size) src dst)
-- the region we are trying to read is enclosed in the sliced region
| (idx - dstOff) < size && 32 <= size - (idx - dstOff) = readWord (Lit $ srcOff + (idx - dstOff)) src
Expand Down
19 changes: 15 additions & 4 deletions test/test.hs
Original file line number Diff line number Diff line change
Expand Up @@ -515,6 +515,21 @@ tests = testGroup "hevm"
let e = BufLength (CopySlice (Lit 0x2) (Lit 0x2) (Lit 0x1) (ConcreteBuf "") (ConcreteBuf ""))
b <- checkEquiv e (Expr.simplify e)
assertBoolM "Simplifier failed" b
, test "simp-readByte1" $ do
let srcOffset = (ReadWord (Lit 0x1) (AbstractBuf "stuff1"))
size = (ReadWord (Lit 0x1) (AbstractBuf "stuff2"))
src = (AbstractBuf "stuff2")
e = ReadByte (Lit 0x0) (CopySlice srcOffset (Lit 0x10) size src (AbstractBuf "dst"))
simp = Expr.simplify e
assertEqualM "readByte simplification" simp (ReadByte (Lit 0x0) (AbstractBuf "dst"))
, test "simp-readByte2" $ do
let srcOffset = (ReadWord (Lit 0x1) (AbstractBuf "stuff1"))
size =(Lit 0x1)
src = (AbstractBuf "stuff2")
e = ReadByte (Lit 0x0) (CopySlice srcOffset (Lit 0x10) size src (AbstractBuf "dst"))
simp =Expr.simplify e
res <- checkEquiv e simp
assertEqualM "readByte simplification" res True
, test "simp-max-buflength" $ do
let simp = Expr.simplify $ Max (Lit 0) (BufLength (AbstractBuf "txdata"))
assertEqualM "max-buflength rules" simp $ BufLength (AbstractBuf "txdata")
Expand Down Expand Up @@ -562,10 +577,6 @@ tests = testGroup "hevm"
a = BufLength (ConcreteBuf "ab")
simp = Expr.simplify a
assertEqualM "Must be simplified down to a Lit" simp (Lit 2)
, test "CopySlice-overflow" $ do
let e = ReadWord (Lit 0x0) (CopySlice (Lit 0x0) (Lit 0xfffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc) (Lit 0x6) (ConcreteBuf "\255\255\255\255\255\255") (ConcreteBuf ""))
b <- checkEquiv e (Expr.simplify e)
assertBoolM "Simplifier failed" b
, test "stripWrites-overflow" $ do
-- below eventually boils down to
-- unsafeInto (0xf0000000000000000000000000000000000000000000000000000000000000+1) :: Int
Expand Down
Loading