Yul tests for MemoryStoreRemover

This commit is contained in:
hrkrshnn 2021-03-29 11:18:53 +02:00
parent ed5fae9183
commit f6a82f8efa
25 changed files with 500 additions and 0 deletions

View File

@ -0,0 +1,21 @@
// Test to see if the solver can prove that there is no overflow
// during memory calculations.
{
let x := 0
let y := 100
// can be removed
mstore(x, y)
// reads from [500, 500 + calldatasize())
// since `500 + calldatasize()` does not overflow, it does not read from [0, 32)
// Assuming EIP 1985, the value of calldatasize is at most 2**32.
pop(staticcall(10000, 0, 500, calldatasize(), 0, 0))
}
// ----
// step: memoryStoreRemover
//
// {
// let x := 0
// let y := 100
// pop(y)
// pop(staticcall(10000, 0, 500, calldatasize(), 0, 0))
// }

View File

@ -0,0 +1,21 @@
{
let x := 10
let y := 100
if calldataload(0) {
// should be removed
mstore(x, y)
}
if calldataload(0) {
pop(mload(y))
}
}
// ----
// step: memoryStoreRemover
//
// {
// let x := 10
// let y := 100
// if calldataload(0) { pop(y) }
// if calldataload(0) { pop(mload(y)) }
// }

View File

@ -0,0 +1,32 @@
{
f()
let z := 100
pop(mload(z))
if calldataload(0) {
// does not read from location [20, 52)
pop(keccak256(z, z))
}
function f() {
let x := 10
let y := 20
// can be removed
mstore(x, y)
}
}
// ----
// step: memoryStoreRemover
//
// {
// f()
// let z := 100
// pop(mload(z))
// if calldataload(0) { pop(keccak256(z, z)) }
// function f()
// {
// let x := 10
// let y := 20
// pop(y)
// }
// }

View File

@ -0,0 +1,25 @@
{
let x := 32
let y := 100
// can be removed
mstore(x, y)
if calldataload(0) {
let cds := calldatasize()
// Reads from [0, 32), so does not invalidate location x!
pop(call(1000, 0, 100, 0, 32, 64, 0))
}
}
// ----
// step: memoryStoreRemover
//
// {
// let x := 32
// let y := 100
// pop(y)
// if calldataload(0)
// {
// let cds := calldatasize()
// pop(call(1000, 0, 100, 0, 32, 64, 0))
// }
// }

View File

@ -0,0 +1,23 @@
{
let x := 32
let y := 100
// cannot be removed
mstore(x, y)
let i := 1
for {} lt(i, 10) {i := add(i, 1) } {
// does not read from i, however, we cannot infer this. So, the above mstore
// cannot be removed.
pop(mload(i))
}
}
// ----
// step: memoryStoreRemover
//
// {
// let x := 32
// let y := 100
// mstore(x, y)
// let i := 1
// for { } lt(i, 10) { i := add(i, 1) }
// { pop(mload(i)) }
// }

View File

@ -0,0 +1,22 @@
{
let x := 0
let y := 50
// cannot be removed, since z is not in SSA form
mstore(x, y)
let z := 200
// z is not in SSA form, so the solver would use a free variable.
z := 100
pop(mload(z))
}
// ----
// step: memoryStoreRemover
//
// {
// let x := 0
// let y := 50
// mstore(x, y)
// let z := 200
// z := 100
// pop(mload(z))
// }

View File

@ -0,0 +1,22 @@
{
let x := 0
let y := 10
let i := 0
for {} iszero(i) {i := add(i, 1)}
{
// can be removed!
mstore(x, i)
}
pop(mload(200))
}
// ----
// step: memoryStoreRemover
//
// {
// let x := 0
// let y := 10
// let i := 0
// for { } iszero(i) { i := add(i, 1) }
// { pop(i) }
// pop(mload(200))
// }

View File

@ -0,0 +1,22 @@
{
let x := 0
let y := 10
let i := 0
for {} iszero(i) {i := add(i, 1)}
{
// cannot be removed!
mstore(i, y)
}
pop(mload(200))
}
// ----
// step: memoryStoreRemover
//
// {
// let x := 0
// let y := 10
// let i := 0
// for { } iszero(i) { i := add(i, 1) }
// { mstore(i, y) }
// pop(mload(200))
// }

View File

@ -0,0 +1,19 @@
{
let x := 0
let y := 10
f(x, y)
function f(a, b) {
// cannot be removed, since a and b are considered as free variables
mstore(a, b)
}
}
// ----
// step: memoryStoreRemover
//
// {
// let x := 0
// let y := 10
// f(x, y)
// function f(a, b)
// { mstore(a, b) }
// }

View File

@ -0,0 +1,16 @@
{
let x := 0
let y := 32
// can be removed
mstore(x, y)
return(0, 0)
}
// ----
// step: memoryStoreRemover
//
// {
// let x := 0
// let y := 32
// pop(y)
// return(0, 0)
// }

View File

@ -0,0 +1,19 @@
{
// 2**128
let x := 340282366920938463463374607431768211456
// The optimization step will remove the following `mstore`.
// EIP 1985 limits `msize()` to `2**32` and the `mstore`
// beyond the region would result in out of gas.
// By removing `mstore`, we are converting a snippet
// that will be always OOG into one that would execute.
mstore(x, 100)
sstore(0, 10)
}
// ----
// step: memoryStoreRemover
//
// {
// let x := 340282366920938463463374607431768211456
// pop(100)
// sstore(0, 10)
// }

View File

@ -0,0 +1,15 @@
// Test to see if the rule is applied in presence of msize
{
pop(msize())
let x := 100
// cannot be removed because of the msize
mstore(x, 100)
}
// ----
// step: memoryStoreRemover
//
// {
// pop(msize())
// let x := 100
// mstore(x, 100)
// }

View File

@ -0,0 +1,20 @@
{
let x := 0
let y := 100
// Actually cannot be removed.
mstore(x, y)
// Even though this cannot happen in practice,
// we'll unfortunately have to deal with this situation.
// reads from bytes 2*256 - 1, 0, ..., 30
pop(mload(115792089237316195423570985008687907853269984665640564039457584007913129639935))
}
// ----
// step: memoryStoreRemover
//
// {
// let x := 0
// let y := 100
// mstore(x, y)
// pop(mload(115792089237316195423570985008687907853269984665640564039457584007913129639935))
// }

View File

@ -0,0 +1,19 @@
{
let x := 115792089237316195423570985008687907853269984665640564039457584007913129639935
let y := 1000
// Cannot be removed, since it writes to bytes
// 2**256 - 1, 0, 1, ..., 30
mstore(x, y)
// reads from [0, 32)
pop(mload(0))
}
// ----
// step: memoryStoreRemover
//
// {
// let x := 115792089237316195423570985008687907853269984665640564039457584007913129639935
// let y := 1000
// mstore(x, y)
// pop(mload(0))
// }

View File

@ -0,0 +1,13 @@
{
let x := 10
let y := 20
mstore(x, y)
}
// ----
// step: memoryStoreRemover
//
// {
// let x := 10
// let y := 20
// pop(y)
// }

View File

@ -0,0 +1,29 @@
{
let x := 0
// y is not a SSA Variable
let y := 20
if calldataload(10) {
y := 100
}
// The location is not read from.
// Even though the value is not an identifier, let alone an SSA variable.
mstore(x, calldataload(y))
mstore(x, y)
// does not read from memory
pop(extcodesize(0))
// does not read from [0, 32)
log0(100, 200)
}
// ----
// step: memoryStoreRemover
//
// {
// let x := 0
// let y := 20
// if calldataload(10) { y := 100 }
// pop(calldataload(y))
// pop(y)
// pop(extcodesize(0))
// log0(100, 200)
// }

View File

@ -0,0 +1,17 @@
{
let x := 10
let y := 60
// can be removed
mstore(x, y)
// Does not read from [10, 42)
pop(mload(y))
}
// ----
// step: memoryStoreRemover
//
// {
// let x := 10
// let y := 60
// pop(y)
// pop(mload(y))
// }

View File

@ -0,0 +1,17 @@
{
let x := 10
let y := 20
// This should not be removed
mstore(x, y)
// reads from x
pop(mload(x))
}
// ----
// step: memoryStoreRemover
//
// {
// let x := 10
// let y := 20
// mstore(x, y)
// pop(mload(x))
// }

View File

@ -0,0 +1,19 @@
{
let x := 10
let y := 10
// should not be removed because of the if statement
mstore(x, y)
if calldataload(0) {
// reads inside control flow
pop(mload(x))
}
}
// ----
// step: memoryStoreRemover
//
// {
// let x := 10
// let y := 10
// mstore(x, y)
// if calldataload(0) { pop(mload(x)) }
// }

View File

@ -0,0 +1,19 @@
{
// x is not in SSA form
let x := 10
if calldataload(0) {
x := 25
}
let y := 20
// Should not be removed because x is not in SSA form
mstore(x, y)
}
// ----
// step: memoryStoreRemover
//
// {
// let x := 10
// if calldataload(0) { x := 25 }
// let y := 20
// mstore(x, y)
// }

View File

@ -0,0 +1,21 @@
{
let x := 10
let y := 20
let z := 30
// even though `x` is assigned twice, both `mstores` can be removed.
mstore(x, y)
mstore(x, z)
pop(mload(100))
}
// ----
// step: memoryStoreRemover
//
// {
// let x := 10
// let y := 20
// let z := 30
// pop(y)
// pop(z)
// pop(mload(100))
// }

View File

@ -0,0 +1,19 @@
{
let x := 10
let y := 20
pop(mload(x))
// can't be removed even though nothing is read afterwards, because we'll check reads from the
// entire block.
mstore(x, y)
}
// ----
// step: memoryStoreRemover
//
// {
// let x := 10
// let y := 20
// pop(mload(x))
// mstore(x, y)
// }

View File

@ -0,0 +1,21 @@
{
f()
function f() {
let x := 10
let y := 20
// will never be read, so can be removed
mstore(x, y)
}
}
// ----
// step: memoryStoreRemover
//
// {
// f()
// function f()
// {
// let x := 10
// let y := 20
// pop(y)
// }
// }

View File

@ -0,0 +1,24 @@
{
f()
pop(mload(16))
function f() {
let x := 10
let y := 20
// cannot be removed
mstore(x, y)
}
}
// ----
// step: memoryStoreRemover
//
// {
// f()
// pop(mload(16))
// function f()
// {
// let x := 10
// let y := 20
// mstore(x, y)
// }
// }

View File

@ -0,0 +1,5 @@
{ }
// ----
// step: memoryStoreRemover
//
// { }