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

Open
wants to merge 15 commits into
base: main
Choose a base branch
from
3 changes: 3 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,9 @@ 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
- Two more simplification rules: `ReadByte` & `ReadWord` when the `CopySlice`
it is reading from 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
34 changes: 30 additions & 4 deletions test/test.hs
Original file line number Diff line number Diff line change
Expand Up @@ -515,6 +515,36 @@ 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
blishko marked this conversation as resolved.
Show resolved Hide resolved
assertEqualM "readByte simplification" res True
, test "simp-readWord1" $ do
let srcOffset = (ReadWord (Lit 0x1) (AbstractBuf "stuff1"))
size = (ReadWord (Lit 0x1) (AbstractBuf "stuff2"))
src = (AbstractBuf "stuff2")
e = ReadWord (Lit 0x1) (CopySlice srcOffset (Lit 0x40) size src (AbstractBuf "dst"))
simp = Expr.simplify e
assertEqualM "readWord simplification" simp (ReadWord (Lit 0x1) (AbstractBuf "dst"))
, test "simp-readWord2" $ do
let srcOffset = (ReadWord (Lit 0x12) (AbstractBuf "stuff1"))
size = (Lit 0x1)
src = (AbstractBuf "stuff2")
e = ReadWord (Lit 0x12) (CopySlice srcOffset (Lit 0x50) size src (AbstractBuf "dst"))
simp = Expr.simplify e
res <- checkEquiv e simp
assertEqualM "readWord 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 +592,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