diff --git a/test/cmdlineTests/gas_test_abiv2/output b/test/cmdlineTests/gas_test_abiv2/output index f555b7ffd..8815bd743 100644 --- a/test/cmdlineTests/gas_test_abiv2/output +++ b/test/cmdlineTests/gas_test_abiv2/output @@ -2,11 +2,11 @@ ======= gas_test_abiv2/input.sol:C ======= Gas estimation: construction: - 1140 + 1096600 = 1097740 + 1160 + 1115800 = 1116960 external: a(): 530 - b(uint256): 1118 - f1(uint256): 586 + b(uint256): infinite + f1(uint256): infinite f2(uint256[],string[],uint16,address): infinite f3(uint16[],string[],uint16,address): infinite f4(uint32[],string[12],bytes[2][],address): infinite diff --git a/test/cmdlineTests/gas_test_abiv2_optimize_yul/output b/test/cmdlineTests/gas_test_abiv2_optimize_yul/output index 8a77186cb..9b385e47f 100644 --- a/test/cmdlineTests/gas_test_abiv2_optimize_yul/output +++ b/test/cmdlineTests/gas_test_abiv2_optimize_yul/output @@ -2,7 +2,7 @@ ======= gas_test_abiv2_optimize_yul/input.sol:C ======= Gas estimation: construction: - 651 + 617200 = 617851 + 651 + 616600 = 617251 external: a(): 429 b(uint256): 884 diff --git a/test/libsolidity/ABIDecoderTests.cpp b/test/libsolidity/ABIDecoderTests.cpp index 9eb0d3c4c..2923d2b61 100644 --- a/test/libsolidity/ABIDecoderTests.cpp +++ b/test/libsolidity/ABIDecoderTests.cpp @@ -108,6 +108,7 @@ BOOST_AUTO_TEST_CASE(cleanup) } } )"; + bool newDecoder = false; BOTH_ENCODERS( compileAndRun(sourceCode); ABI_CHECK( @@ -119,8 +120,44 @@ BOOST_AUTO_TEST_CASE(cleanup) "f(uint16,int16,address,bytes3,bool)", u256(0xffffff), u256(0x1ffff), u256(-1), string("abcd"), u256(1) ), - encodeArgs(u256(0xffff), u256(-1), (u256(1) << 160) - 1, string("abc"), true) + newDecoder ? bytes{} : encodeArgs(u256(0xffff), u256(-1), (u256(1) << 160) - 1, string("abc"), true) ); + ABI_CHECK( + callContractFunction( + "f(uint16,int16,address,bytes3,bool)", + u256(0xffffff), u256(0), u256(0), string("bcd"), u256(1) + ), + newDecoder ? bytes{} : encodeArgs(u256(0xffff), u256(0), 0, string("bcd"), true) + ); + ABI_CHECK( + callContractFunction( + "f(uint16,int16,address,bytes3,bool)", + u256(0), u256(0x1ffff), u256(0), string("ab"), u256(1) + ), + newDecoder ? bytes{} : encodeArgs(u256(0), u256(-1), 0, string("ab"), true) + ); + ABI_CHECK( + callContractFunction( + "f(uint16,int16,address,bytes3,bool)", + u256(0), u256(0), u256(-1), string("ad"), u256(1) + ), + newDecoder ? bytes{} : encodeArgs(u256(0), u256(0), (u256(1) << 160) - 1, string("ad"), true) + ); + ABI_CHECK( + callContractFunction( + "f(uint16,int16,address,bytes3,bool)", + u256(0), u256(0), u256(0), string("abcd"), u256(1) + ), + newDecoder ? bytes{} : encodeArgs(u256(0), u256(0), 0, string("abc"), true) + ); + ABI_CHECK( + callContractFunction( + "f(uint16,int16,address,bytes3,bool)", + u256(0), u256(0), u256(0), string("abc"), u256(2) + ), + newDecoder ? bytes{} : encodeArgs(u256(0), u256(0), 0, string("abc"), true) + ); + newDecoder = true; ) } @@ -506,7 +543,7 @@ BOOST_AUTO_TEST_CASE(short_input_bytes) ) } -BOOST_AUTO_TEST_CASE(cleanup_int_inside_arrays) +BOOST_AUTO_TEST_CASE(validation_int_inside_arrays) { string sourceCode = R"( contract C { @@ -521,15 +558,69 @@ BOOST_AUTO_TEST_CASE(cleanup_int_inside_arrays) ABI_CHECK(callContractFunction("f(uint16[])", 0x20, 1, 7), encodeArgs(7)); ABI_CHECK(callContractFunction("g(int16[])", 0x20, 1, 7), encodeArgs(7)); ABI_CHECK(callContractFunction("f(uint16[])", 0x20, 1, u256("0xffff")), encodeArgs(u256("0xffff"))); - ABI_CHECK(callContractFunction("g(int16[])", 0x20, 1, u256("0xffff")), encodeArgs(u256(-1))); - ABI_CHECK(callContractFunction("f(uint16[])", 0x20, 1, u256("0x1ffff")), encodeArgs(u256("0xffff"))); - ABI_CHECK(callContractFunction("g(int16[])", 0x20, 1, u256("0x10fff")), encodeArgs(u256("0x0fff"))); + ABI_CHECK(callContractFunction("g(int16[])", 0x20, 1, u256("0xffff")), encodeArgs()); + ABI_CHECK(callContractFunction("f(uint16[])", 0x20, 1, u256("0x1ffff")), encodeArgs()); + ABI_CHECK(callContractFunction("g(int16[])", 0x20, 1, u256("0x10fff")), encodeArgs()); ABI_CHECK(callContractFunction("h(uint8[])", 0x20, 1, 0), encodeArgs(u256(0))); ABI_CHECK(callContractFunction("h(uint8[])", 0x20, 1, 1), encodeArgs(u256(1))); ABI_CHECK(callContractFunction("h(uint8[])", 0x20, 1, 2), encodeArgs()); ) } +BOOST_AUTO_TEST_CASE(validation_function_type) +{ + string sourceCode = R"( + contract C { + function f(function () external) public pure returns (uint r) { r = 1; } + function g(function () external[] memory) public pure returns (uint r) { r = 2; } + function h(function () external[] calldata) external pure returns (uint r) { r = 3; } + function i(function () external[] calldata a) external pure returns (uint r) { a[0]; r = 4; } + } + )"; + bool newDecoder = false; + string validFun{"01234567890123456789abcd"}; + string invalidFun{"01234567890123456789abcdX"}; + BOTH_ENCODERS( + compileAndRun(sourceCode); + ABI_CHECK(callContractFunction("f(function)", validFun), encodeArgs(1)); + ABI_CHECK(callContractFunction("f(function)", invalidFun), newDecoder ? bytes{} : encodeArgs(1)); + ABI_CHECK(callContractFunction("g(function[])", 0x20, 1, validFun), encodeArgs(2)); + ABI_CHECK(callContractFunction("g(function[])", 0x20, 1, invalidFun), newDecoder ? bytes{} : encodeArgs(2)); + ABI_CHECK(callContractFunction("h(function[])", 0x20, 1, validFun), encodeArgs(3)); + // No failure because the data is not accessed. + ABI_CHECK(callContractFunction("h(function[])", 0x20, 1, invalidFun), encodeArgs(3)); + ABI_CHECK(callContractFunction("i(function[])", 0x20, 1, validFun), encodeArgs(4)); + ABI_CHECK(callContractFunction("i(function[])", 0x20, 1, invalidFun), newDecoder ? bytes{} : encodeArgs(4)); + newDecoder = true; + ) +} + +BOOST_AUTO_TEST_CASE(validation_function_type_inside_struct) +{ + string sourceCode = R"( + contract C { + struct S { function () external x; } + function f(S memory) public pure returns (uint r) { r = 1; } + function g(S calldata) external pure returns (uint r) { r = 2; } + function h(S calldata s) external pure returns (uint r) { s.x; r = 3; } + } + )"; + string validFun{"01234567890123456789abcd"}; + string invalidFun{"01234567890123456789abcdX"}; + NEW_ENCODER( + compileAndRun(sourceCode); + ABI_CHECK(callContractFunction("f((function))", validFun), encodeArgs(1)); + // Error because we copy to memory + ABI_CHECK(callContractFunction("f((function))", invalidFun), encodeArgs()); + ABI_CHECK(callContractFunction("g((function))", validFun), encodeArgs(2)); + // No error because x is not accessed. + ABI_CHECK(callContractFunction("g((function))", invalidFun), encodeArgs(2)); + ABI_CHECK(callContractFunction("h((function))", validFun), encodeArgs(3)); + // Error on access. + ABI_CHECK(callContractFunction("h((function))", invalidFun), encodeArgs()); + ) +} + BOOST_AUTO_TEST_CASE(storage_ptr) { string sourceCode = R"( @@ -583,7 +674,7 @@ BOOST_AUTO_TEST_CASE(struct_simple) ) } -BOOST_AUTO_TEST_CASE(struct_cleanup) +BOOST_AUTO_TEST_CASE(struct_validation) { string sourceCode = R"( contract C { @@ -597,11 +688,24 @@ BOOST_AUTO_TEST_CASE(struct_cleanup) } } )"; + u256 largeNeg("0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff01"); NEW_ENCODER( compileAndRun(sourceCode, 0, "C"); ABI_CHECK( - callContractFunction("f((int16,uint8,bytes2))", 0xff010, 0xff0002, "abcd"), - encodeArgs(u256("0xfffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff010"), 2, "ab") + callContractFunction("f((int16,uint8,bytes2))", largeNeg, 0xff, "ab"), + encodeArgs(largeNeg, 0xff, "ab") + ); + ABI_CHECK( + callContractFunction("f((int16,uint8,bytes2))", 0xff010, 0xff, "ab"), + encodeArgs() + ); + ABI_CHECK( + callContractFunction("f((int16,uint8,bytes2))", largeNeg, 0xff0002, "ab"), + encodeArgs() + ); + ABI_CHECK( + callContractFunction("f((int16,uint8,bytes2))", largeNeg, 0xff, "abcd"), + encodeArgs() ); ) } diff --git a/test/libsolidity/SolidityEndToEndTest.cpp b/test/libsolidity/SolidityEndToEndTest.cpp index 127e60e19..30c3b5fd0 100644 --- a/test/libsolidity/SolidityEndToEndTest.cpp +++ b/test/libsolidity/SolidityEndToEndTest.cpp @@ -8244,8 +8244,8 @@ BOOST_AUTO_TEST_CASE(calldata_struct_cleaning) // double check that the valid case goes through ABI_CHECK(callContractFunction("f((uint8,bytes1))", u256(0x12), bytes{0x34} + bytes(31,0)), encodeArgs(0x12, bytes{0x34} + bytes(31,0))); - ABI_CHECK(callContractFunction("f((uint8,bytes1))", u256(0x1234), bytes{0x56, 0x78} + bytes(30,0)), encodeArgs(0x34, bytes{0x56} + bytes(31,0))); - ABI_CHECK(callContractFunction("f((uint8,bytes1))", u256(-1), u256(-1)), encodeArgs(0xFF, bytes{0xFF} + bytes(31,0))); + ABI_CHECK(callContractFunction("f((uint8,bytes1))", u256(0x1234), bytes{0x56, 0x78} + bytes(30,0)), encodeArgs()); + ABI_CHECK(callContractFunction("f((uint8,bytes1))", u256(-1), u256(-1)), encodeArgs()); } BOOST_AUTO_TEST_CASE(calldata_struct_function_type)