diff --git a/Changelog.md b/Changelog.md index 6f8c48f6e..96fc9f5a0 100644 --- a/Changelog.md +++ b/Changelog.md @@ -5,6 +5,7 @@ Important Bugfixes: * Type System: Use correct type name for contracts in event parameters when used in libraries. This affected code generation. Bugfixes: + * ABIEncoderV2: Refuse to generate code that is known to be potentially buggy. * General: Split rule list such that JavaScript environments with small stacks can use the compiler. diff --git a/libsolidity/codegen/ABIFunctions.cpp b/libsolidity/codegen/ABIFunctions.cpp index 3e3aa0ae4..02b66297b 100644 --- a/libsolidity/codegen/ABIFunctions.cpp +++ b/libsolidity/codegen/ABIFunctions.cpp @@ -679,6 +679,16 @@ string ABIFunctions::abiEncodingFunctionSimpleArray( _encodeAsLibraryTypes, false )); + solAssert( + inMemory || + !_from.baseType()->isValueType() || + ( + _from.baseType()->category() == Type::Category::Integer && + !dynamic_cast(*_from.baseType()).isSigned() + ) || + _from.baseType()->storageBytes() == 32, + "You are using a buggy part of ABIEncoderV2. Please use a newer compiler version or disable ABIEncoderV2." + ); templ("arrayElementAccess", inMemory ? "mload(srcPtr)" : _from.baseType()->isValueType() ? "sload(srcPtr)" : "srcPtr" ); templ("nextArrayElement", nextArrayElementFunction(_from)); return templ.render(); @@ -777,6 +787,12 @@ string ABIFunctions::abiEncodingFunctionCompactStorageArray( } else { + // This function is not always a problem, but it can overwrite other data areas. + solAssert( + false, + "You are using a potentially buggy part of ABIEncoderV2. Please use a newer compiler version or disable ABIEncoderV2." + ); + // Multiple items per slot solAssert(_from.baseType()->storageBytes() <= 16, ""); solAssert(!_from.baseType()->isDynamicallyEncoded(), ""); @@ -927,6 +943,16 @@ string ABIFunctions::abiEncodingFunctionStruct( } else memberTempl("preprocess", ""); + + solAssert( + ( + memberTypeFrom->category() == Type::Category::Integer && + !dynamic_cast(*memberTypeFrom).isSigned() + ) || + memberTypeFrom->storageBytes() == 32, + "You are using a potentially buggy part of ABIEncoderV2. Please use a newer compiler version or disable ABIEncoderV2." + ); + memberTempl("retrieveValue", shiftRightFunction(intraSlotOffset * 8) + "(slotValue)"); } else diff --git a/test/libsolidity/ABIEncoderTests.cpp b/test/libsolidity/ABIEncoderTests.cpp index 49db9ce1c..c0dad35da 100644 --- a/test/libsolidity/ABIEncoderTests.cpp +++ b/test/libsolidity/ABIEncoderTests.cpp @@ -293,34 +293,6 @@ BOOST_AUTO_TEST_CASE(storage_array_dyn) ) } -BOOST_AUTO_TEST_CASE(storage_array_compact) -{ - string sourceCode = R"( - contract C { - int72[] x; - event E(int72[]); - function f() public { - x.push(-1); - x.push(2); - x.push(-3); - x.push(4); - x.push(-5); - x.push(6); - x.push(-7); - x.push(8); - E(x); - } - } - )"; - BOTH_ENCODERS( - compileAndRun(sourceCode); - callContractFunction("f()"); - REQUIRE_LOG_DATA(encodeArgs( - 0x20, 8, u256(-1), 2, u256(-3), 4, u256(-5), 6, u256(-7), 8 - )); - ) -} - BOOST_AUTO_TEST_CASE(external_function) { string sourceCode = R"( @@ -412,44 +384,6 @@ BOOST_AUTO_TEST_CASE(function_name_collision) ) } -BOOST_AUTO_TEST_CASE(structs) -{ - string sourceCode = R"( - contract C { - struct S { uint16 a; uint16 b; T[] sub; uint16 c; } - struct T { uint64[2] x; } - S s; - event e(uint16, S); - function f() public returns (uint, S) { - uint16 x = 7; - s.a = 8; - s.b = 9; - s.c = 10; - s.sub.length = 3; - s.sub[0].x[0] = 11; - s.sub[1].x[0] = 12; - s.sub[2].x[1] = 13; - e(x, s); - return (x, s); - } - } - )"; - - NEW_ENCODER( - compileAndRun(sourceCode, 0, "C"); - bytes encoded = encodeArgs( - u256(7), 0x40, - 8, 9, 0x80, 10, - 3, - 11, 0, - 12, 0, - 0, 13 - ); - BOOST_CHECK(callContractFunction("f()") == encoded); - REQUIRE_LOG_DATA(encoded); - ) -} - BOOST_AUTO_TEST_CASE(empty_struct) { string sourceCode = R"(