Skip to content

Commit af8e6c0

Browse files
authored
Merge pull request #655 from ethereum/more-simpl-as-needed
Two simplifications that will be needed to deal with @zoep's issues regarding initcode equivalence
2 parents 6bbcf1f + 8244af0 commit af8e6c0

File tree

3 files changed

+39
-4
lines changed

3 files changed

+39
-4
lines changed

CHANGELOG.md

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,9 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
2020
generated via iterative calls to the SMT solver for quicker solving
2121
- Aliasing works much better for symbolic and concrete addresses
2222
- Constant propagation for symbolic values
23+
- Two more simplification rules: `ReadByte` & `ReadWord` when the `CopySlice`
24+
it is reading from is writing after the position being read, so the
25+
`CopySlice` can be ignored
2326

2427
## Fixed
2528
- We now try to simplify expressions fully before trying to cast them to a concrete value

src/EVM/Expr.hs

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -243,6 +243,9 @@ readByte i@(Lit x) (WriteWord (Lit idx) val src)
243243
(Lit _) -> indexWord (Lit $ x - idx) val
244244
_ -> IndexWord (Lit $ x - idx) val
245245
else readByte i src
246+
-- reading a byte that is lower than the dstOffset of a CopySlice, so it's just reading from dst
247+
readByte i@(Lit x) (CopySlice _ (Lit dstOffset) _ _ dst) | dstOffset > x =
248+
readByte i dst
246249
readByte i@(Lit x) (CopySlice (Lit srcOffset) (Lit dstOffset) (Lit size) src dst)
247250
= if x - dstOffset < size
248251
then readByte (Lit $ x - (dstOffset - srcOffset)) src
@@ -279,6 +282,9 @@ readWord idx b@(WriteWord idx' val buf)
279282
-- we do not have enough information to statically determine whether or not
280283
-- the region we want to read overlaps the WriteWord
281284
_ -> readWordFromBytes idx b
285+
-- reading a Word that is lower than the dstOffset-32 of a CopySlice, so it's just reading from dst
286+
readWord i@(Lit x) (CopySlice _ (Lit dstOffset) _ _ dst) | dstOffset > x+32 =
287+
readWord i dst
282288
readWord (Lit idx) b@(CopySlice (Lit srcOff) (Lit dstOff) (Lit size) src dst)
283289
-- the region we are trying to read is enclosed in the sliced region
284290
| (idx - dstOff) < size && 32 <= size - (idx - dstOff) = readWord (Lit $ srcOff + (idx - dstOff)) src

test/test.hs

Lines changed: 30 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -515,6 +515,36 @@ tests = testGroup "hevm"
515515
let e = BufLength (CopySlice (Lit 0x2) (Lit 0x2) (Lit 0x1) (ConcreteBuf "") (ConcreteBuf ""))
516516
b <- checkEquiv e (Expr.simplify e)
517517
assertBoolM "Simplifier failed" b
518+
, test "simp-readByte1" $ do
519+
let srcOffset = (ReadWord (Lit 0x1) (AbstractBuf "stuff1"))
520+
size = (ReadWord (Lit 0x1) (AbstractBuf "stuff2"))
521+
src = (AbstractBuf "stuff2")
522+
e = ReadByte (Lit 0x0) (CopySlice srcOffset (Lit 0x10) size src (AbstractBuf "dst"))
523+
simp = Expr.simplify e
524+
assertEqualM "readByte simplification" simp (ReadByte (Lit 0x0) (AbstractBuf "dst"))
525+
, test "simp-readByte2" $ do
526+
let srcOffset = (ReadWord (Lit 0x1) (AbstractBuf "stuff1"))
527+
size = (Lit 0x1)
528+
src = (AbstractBuf "stuff2")
529+
e = ReadByte (Lit 0x0) (CopySlice srcOffset (Lit 0x10) size src (AbstractBuf "dst"))
530+
simp = Expr.simplify e
531+
res <- checkEquiv e simp
532+
assertEqualM "readByte simplification" res True
533+
, test "simp-readWord1" $ do
534+
let srcOffset = (ReadWord (Lit 0x1) (AbstractBuf "stuff1"))
535+
size = (ReadWord (Lit 0x1) (AbstractBuf "stuff2"))
536+
src = (AbstractBuf "stuff2")
537+
e = ReadWord (Lit 0x1) (CopySlice srcOffset (Lit 0x40) size src (AbstractBuf "dst"))
538+
simp = Expr.simplify e
539+
assertEqualM "readWord simplification" simp (ReadWord (Lit 0x1) (AbstractBuf "dst"))
540+
, test "simp-readWord2" $ do
541+
let srcOffset = (ReadWord (Lit 0x12) (AbstractBuf "stuff1"))
542+
size = (Lit 0x1)
543+
src = (AbstractBuf "stuff2")
544+
e = ReadWord (Lit 0x12) (CopySlice srcOffset (Lit 0x50) size src (AbstractBuf "dst"))
545+
simp = Expr.simplify e
546+
res <- checkEquiv e simp
547+
assertEqualM "readWord simplification" res True
518548
, test "simp-max-buflength" $ do
519549
let simp = Expr.simplify $ Max (Lit 0) (BufLength (AbstractBuf "txdata"))
520550
assertEqualM "max-buflength rules" simp $ BufLength (AbstractBuf "txdata")
@@ -562,10 +592,6 @@ tests = testGroup "hevm"
562592
a = BufLength (ConcreteBuf "ab")
563593
simp = Expr.simplify a
564594
assertEqualM "Must be simplified down to a Lit" simp (Lit 2)
565-
, test "CopySlice-overflow" $ do
566-
let e = ReadWord (Lit 0x0) (CopySlice (Lit 0x0) (Lit 0xfffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc) (Lit 0x6) (ConcreteBuf "\255\255\255\255\255\255") (ConcreteBuf ""))
567-
b <- checkEquiv e (Expr.simplify e)
568-
assertBoolM "Simplifier failed" b
569595
, test "stripWrites-overflow" $ do
570596
-- below eventually boils down to
571597
-- unsafeInto (0xf0000000000000000000000000000000000000000000000000000000000000+1) :: Int

0 commit comments

Comments
 (0)