Fix wrong cleanup when copying from calldata to memory

Co-authored-by: Kamil Śliwak <kamil.sliwak@codepoets.it>
This commit is contained in:
Marenz
2022-08-08 13:07:16 +02:00
committed by Daniel Kirchner
co-authored by Kamil Śliwak
parent 5b0f4a724a
commit 22c7cd22b9
48 changed files with 396 additions and 211 deletions
@@ -60,10 +60,10 @@ contract C {
// EVMVersion: >homestead
// ----
// test_bytes() ->
// gas irOptimized: 367365
// gas legacy: 416585
// gas legacyOptimized: 322043
// gas irOptimized: 362445
// gas legacy: 414569
// gas legacyOptimized: 319271
// test_uint256() ->
// gas irOptimized: 515982
// gas legacy: 583100
// gas legacyOptimized: 444161
// gas irOptimized: 511910
// gas legacy: 581876
// gas legacyOptimized: 442757
@@ -51,6 +51,6 @@ contract C {
// f2() -> 0x20, 0xa0, 0x1, 0x60, 0x2, 0x3, "abc"
// f3() -> 0x20, 0xa0, 0x1, 0x60, 0x2, 0x3, "abc"
// f4() -> 0x20, 0x160, 0x1, 0x80, 0xc0, 0x2, 0x3, "abc", 0x7, 0x40, 0x2, 0x2, 0x3
// gas irOptimized: 112820
// gas legacy: 114900
// gas legacyOptimized: 112606
// gas irOptimized: 112646
// gas legacy: 114866
// gas legacyOptimized: 112586
@@ -0,0 +1,17 @@
pragma abicoder v2;
struct T {
bytes x;
uint[3] y;
}
contract E {
function f(bool a, T calldata b, bytes32[2] calldata c)
public
returns (bool, T calldata, bytes32[2] calldata)
{
return (a, b, c);
}
}
// ----
// f(bool,(bytes,uint256[3]),bytes32[2]): 1, 0x80, "a", "b", 0x80, 11, 12, 13, 4, "abcd" -> 1, 0x80, "a", "b", 0x80, 11, 12, 13, 4, "abcd"
@@ -20,6 +20,6 @@ contract C {
// f(uint256[][1]): 32, 32, 0 -> true
// f(uint256[][1]): 32, 32, 1, 42 -> true
// f(uint256[][1]): 32, 32, 8, 421, 422, 423, 424, 425, 426, 427, 428 -> true
// gas irOptimized: 128098
// gas legacy: 140672
// gas legacyOptimized: 119588
// gas irOptimized: 127347
// gas legacy: 140553
// gas legacyOptimized: 119450
@@ -0,0 +1,17 @@
library L {
// This case used to be affected by the buggy cleanup due to ABIEncoderV2HeadOverflowWithStaticArrayCleanup bug.
function g(uint[] memory a, uint[1] calldata b) public returns (uint[] memory, uint[1] calldata) {
return (a, b);
}
}
contract C {
function f(uint[] memory a, uint[1] calldata b) public returns (uint[] memory, uint[1] memory) {
return L.g(a, b);
}
}
// ====
// EVMVersion: >homestead
// ----
// library: L
// f(uint256[],uint256[1]): 0x40, 0xff, 1, 0xffff -> 0x40, 0xff, 0x01, 0xffff
@@ -0,0 +1,27 @@
contract C {
function f(string calldata x) external returns (bytes memory r) {
uint mptr;
assembly {
// dirty memory
mptr := mload(0x40)
for { let i := mptr } lt(i, add(mptr, 0x0100)) { i := add(i, 32) }
{
mstore(i, sub(0, 1))
}
}
r = abi.encode(x);
assembly {
// assert that we dirtied the memory that was encoded to
if iszero(eq(mptr, r)) {
revert(0, 0)
}
}
}
function test() external returns (bytes memory) {
return this.f("abc");
}
}
// ====
// EVMVersion: >homestead
// ----
// test() -> 0x20, 0x60, 0x20, 3, "abc"
@@ -0,0 +1,13 @@
contract C {
function f(uint256[] memory a, bytes calldata b) public returns (bytes memory) {
return abi.encode(a, b);
}
function g(uint256[] memory a, bytes calldata b) external returns (bytes memory) {
return f(a, b);
}
}
// ----
// f(uint256[],bytes): 0x40, 0x80, 1, 0xFF, 6, "123456" -> 0x20, 0xc0, 0x40, 0x80, 1, 0xff, 6, "123456"
// g(uint256[],bytes): 0x40, 0x80, 1, 0xffff, 8, "12345678" -> 0x20, 0xc0, 0x40, 0x80, 1, 0xffff, 8, "12345678"
@@ -0,0 +1,18 @@
contract C {
function f(uint256[] memory a, uint256[1] calldata b) public returns (bytes memory) {
return abi.encode(a, b);
}
function g(uint256[] memory a, uint256[1] calldata b) external returns (bytes memory) {
return f(a, b);
}
function h(uint256[] memory a, uint256[1] calldata b) external returns (uint256[] memory, uint256[1] calldata) {
return (a, b);
}
}
// ----
// f(uint256[],uint256[1]): 0x40, 0xff, 1, 0xffff -> 0x20, 0x80, 0x40, 0xff, 1, 0xffff
// g(uint256[],uint256[1]): 0x40, 0xff, 1, 0xffff -> 0x20, 0x80, 0x40, 0xff, 1, 0xffff
// h(uint256[],uint256[1]): 0x40, 0xff, 1, 0xffff -> 0x40, 0xff, 1, 0xffff
@@ -18,10 +18,10 @@ contract C {
// EVMVersion: >homestead
// ----
// h(uint256[2][]): 0x20, 3, 123, 124, 223, 224, 323, 324 -> 32, 256, 0x20, 3, 123, 124, 223, 224, 323, 324
// gas irOptimized: 180768
// gas legacy: 184929
// gas legacyOptimized: 181504
// gas irOptimized: 180726
// gas legacy: 184921
// gas legacyOptimized: 181506
// i(uint256[2][2]): 123, 124, 223, 224 -> 32, 128, 123, 124, 223, 224
// gas irOptimized: 112471
// gas legacy: 115468
// gas legacyOptimized: 112988
// gas irOptimized: 112453
// gas legacy: 115460
// gas legacyOptimized: 112990