From 28e01202af0fc38e685f99dfa6f07b593244b32e Mon Sep 17 00:00:00 2001 From: Djordje Mijovic Date: Thu, 26 Nov 2020 17:15:41 +0100 Subject: [PATCH 1/2] [Sol->Yul] Fixing coping from storage to storage. --- libsolidity/codegen/YulUtilFunctions.cpp | 34 +++++++++---------- libsolidity/codegen/YulUtilFunctions.h | 3 +- ...ray_copy_storage_storage_static_static.sol | 2 ++ 3 files changed, 21 insertions(+), 18 deletions(-) diff --git a/libsolidity/codegen/YulUtilFunctions.cpp b/libsolidity/codegen/YulUtilFunctions.cpp index 791e8b5b9..2407fa548 100644 --- a/libsolidity/codegen/YulUtilFunctions.cpp +++ b/libsolidity/codegen/YulUtilFunctions.cpp @@ -1000,10 +1000,9 @@ string YulUtilFunctions::arrayLengthFunction(ArrayType const& _type) }); } -std::string YulUtilFunctions::resizeDynamicArrayFunction(ArrayType const& _type) +std::string YulUtilFunctions::resizeArrayFunction(ArrayType const& _type) { solAssert(_type.location() == DataLocation::Storage, ""); - solAssert(_type.isDynamicallySized(), ""); solUnimplementedAssert(_type.baseType()->storageBytes() <= 32, "..."); if (_type.isByteArray()) @@ -1019,8 +1018,10 @@ std::string YulUtilFunctions::resizeDynamicArrayFunction(ArrayType const& _type) let oldLen := (array) - // Store new length - sstore(array, newLen) + + // Store new length + sstore(array, newLen) + // Size was reduced, clear end of array if lt(newLen, oldLen) { @@ -1041,6 +1042,7 @@ std::string YulUtilFunctions::resizeDynamicArrayFunction(ArrayType const& _type) ("functionName", functionName) ("panic", panicFunction()) ("fetchLength", arrayLengthFunction(_type)) + ("isDynamic", _type.isDynamicallySized()) ("convertToSize", arrayConvertLengthToSize(_type)) ("dataPosition", arrayDataAreaFunction(_type)) ("clearStorageRange", clearStorageRangeFunction(*_type.baseType())) @@ -1425,7 +1427,7 @@ string YulUtilFunctions::clearStorageArrayFunction(ArrayType const& _type) )") ("functionName", functionName) ("dynamic", _type.isDynamicallySized()) - ("resizeArray", _type.isDynamicallySized() ? resizeDynamicArrayFunction(_type) : "") + ("resizeArray", _type.isDynamicallySized() ? resizeArrayFunction(_type) : "") ( "clearRange", clearStorageRangeFunction( @@ -1497,6 +1499,9 @@ string YulUtilFunctions::copyArrayToStorageFunction(ArrayType const& _fromType, *_fromType.copyForLocation(_toType.location(), _toType.isPointer()) == dynamic_cast(_toType), "" ); + if (!_toType.isDynamicallySized()) + solAssert(!_fromType.isDynamicallySized() && _fromType.length() <= _toType.length(), ""); + if (_fromType.isByteArray()) return copyByteArrayToStorageFunction(_fromType, _toType); if (_fromType.dataStoredIn(DataLocation::Storage) && _toType.baseType()->isValueType()) @@ -1508,9 +1513,8 @@ string YulUtilFunctions::copyArrayToStorageFunction(ArrayType const& _fromType, function (slot, value, len) { if eq(slot, value) { leave } let length := (value, len) - - (slot, length) - + + (slot, length) let srcPtr := (value) @@ -1564,7 +1568,6 @@ string YulUtilFunctions::copyArrayToStorageFunction(ArrayType const& _fromType, bool fromMemory = _fromType.dataStoredIn(DataLocation::Memory); templ("fromMemory", fromMemory); templ("fromCalldata", fromCalldata); - templ("isToDynamic", _toType.isDynamicallySized()); templ("srcDataLocation", arrayDataAreaFunction(_fromType)); if (fromCalldata) { @@ -1573,8 +1576,7 @@ string YulUtilFunctions::copyArrayToStorageFunction(ArrayType const& _fromType, if (_fromType.baseType()->isDynamicallyEncoded()) templ("accessCalldataTail", accessCalldataTailFunction(*_fromType.baseType())); } - if (_toType.isDynamicallySized()) - templ("resizeArray", resizeDynamicArrayFunction(_toType)); + templ("resizeArray", resizeArrayFunction(_toType)); templ("arrayLength",arrayLengthFunction(_fromType)); templ("isValueType", _fromType.baseType()->isValueType()); templ("dstDataLocation", arrayDataAreaFunction(_toType)); @@ -1693,6 +1695,8 @@ string YulUtilFunctions::copyValueArrayStorageToStorageFunction(ArrayType const& solAssert(_fromType.dataStoredIn(DataLocation::Storage) && _toType.baseType()->isValueType(), ""); solAssert(_toType.dataStoredIn(DataLocation::Storage), ""); + solUnimplementedAssert(_fromType.storageStride() == _toType.storageStride(), ""); + string functionName = "copy_array_to_storage_from_" + _fromType.identifier() + "_to_" + _toType.identifier(); return m_functionCollector.createFunction(functionName, [&](){ Whiskers templ(R"( @@ -1701,9 +1705,7 @@ string YulUtilFunctions::copyValueArrayStorageToStorageFunction(ArrayType const& let length := (src) // Make sure array length is sane if gt(length, 0xffffffffffffffff) { () } - - (dst, length) - + (dst, length) let srcPtr := (src) @@ -1723,9 +1725,7 @@ string YulUtilFunctions::copyValueArrayStorageToStorageFunction(ArrayType const& if (_fromType.dataStoredIn(DataLocation::Storage)) solAssert(!_fromType.isValueType(), ""); templ("functionName", functionName); - templ("isToDynamic", _toType.isDynamicallySized()); - if (_toType.isDynamicallySized()) - templ("resizeArray", resizeDynamicArrayFunction(_toType)); + templ("resizeArray", resizeArrayFunction(_toType)); templ("arrayLength",arrayLengthFunction(_fromType)); templ("panic", panicFunction()); templ("srcDataLocation", arrayDataAreaFunction(_fromType)); diff --git a/libsolidity/codegen/YulUtilFunctions.h b/libsolidity/codegen/YulUtilFunctions.h index af34c3535..1c2bc9332 100644 --- a/libsolidity/codegen/YulUtilFunctions.h +++ b/libsolidity/codegen/YulUtilFunctions.h @@ -171,8 +171,9 @@ public: std::string arrayLengthFunction(ArrayType const& _type); /// @returns the name of a function that resizes a storage array + /// for statically sized arrays, it will just clean-up elements of array starting from newLen until the end /// signature: (array, newLen) - std::string resizeDynamicArrayFunction(ArrayType const& _type); + std::string resizeArrayFunction(ArrayType const& _type); /// @returns the name of a function that reduces the size of a storage array by one element /// signature: (array) diff --git a/test/libsolidity/semanticTests/array/copying/array_copy_storage_storage_static_static.sol b/test/libsolidity/semanticTests/array/copying/array_copy_storage_storage_static_static.sol index 71601d477..98642c9e1 100644 --- a/test/libsolidity/semanticTests/array/copying/array_copy_storage_storage_static_static.sol +++ b/test/libsolidity/semanticTests/array/copying/array_copy_storage_storage_static_static.sol @@ -13,5 +13,7 @@ contract c { } } +// ==== +// compileViaYul: also // ---- // test() -> 8, 0 From bd86588459498105cbdca205557e328f04e8c936 Mon Sep 17 00:00:00 2001 From: Djordje Mijovic Date: Mon, 30 Nov 2020 17:55:20 +0100 Subject: [PATCH 2/2] Adding more tests for array copying from storage to storage. --- ...ay_copy_storage_storage_different_base.sol | 19 ++++++++++++++++ ...y_copy_storage_storage_dynamic_dynamic.sol | 22 +++++++++++++++++++ .../storage_to_storage_different_base.sol | 9 ++++++++ .../storage_to_storage_different_base_2.sol | 9 ++++++++ .../storage_to_storage_dynamic_to_static.sol | 9 ++++++++ ...ge_to_storage_static_longer_to_shorter.sol | 9 ++++++++ 6 files changed, 77 insertions(+) create mode 100644 test/libsolidity/semanticTests/array/copying/array_copy_storage_storage_different_base.sol create mode 100644 test/libsolidity/semanticTests/array/copying/array_copy_storage_storage_dynamic_dynamic.sol create mode 100644 test/libsolidity/syntaxTests/array/invalidCopy/storage_to_storage_different_base.sol create mode 100644 test/libsolidity/syntaxTests/array/invalidCopy/storage_to_storage_different_base_2.sol create mode 100644 test/libsolidity/syntaxTests/array/invalidCopy/storage_to_storage_dynamic_to_static.sol create mode 100644 test/libsolidity/syntaxTests/array/invalidCopy/storage_to_storage_static_longer_to_shorter.sol diff --git a/test/libsolidity/semanticTests/array/copying/array_copy_storage_storage_different_base.sol b/test/libsolidity/semanticTests/array/copying/array_copy_storage_storage_different_base.sol new file mode 100644 index 000000000..e1b6cfeb1 --- /dev/null +++ b/test/libsolidity/semanticTests/array/copying/array_copy_storage_storage_different_base.sol @@ -0,0 +1,19 @@ +contract c { + uint64[] data1; + uint256[] data2; + + function test() public returns (uint256 x, uint256 y) { + data2.push(11); + data1.push(0); + data1.push(1); + data1.push(2); + data1.push(3); + data1.push(4); + data2 = data1; + assert(data1[0] == data2[0]); + x = data2.length; + y = data2[4]; + } +} +// ---- +// test() -> 5, 4 diff --git a/test/libsolidity/semanticTests/array/copying/array_copy_storage_storage_dynamic_dynamic.sol b/test/libsolidity/semanticTests/array/copying/array_copy_storage_storage_dynamic_dynamic.sol new file mode 100644 index 000000000..7815f0a28 --- /dev/null +++ b/test/libsolidity/semanticTests/array/copying/array_copy_storage_storage_dynamic_dynamic.sol @@ -0,0 +1,22 @@ +contract c { + uint256[] data1; + uint256[] data2; + + function test() public returns (uint256 x, uint256 y) { + data2.push(11); + data1.push(0); + data1.push(1); + data1.push(2); + data1.push(3); + data1.push(4); + data2 = data1; + assert(data1[0] == data2[0]); + x = data2.length; + y = data2[4]; + } +} + +// ==== +// compileViaYul: also +// ---- +// test() -> 5, 4 diff --git a/test/libsolidity/syntaxTests/array/invalidCopy/storage_to_storage_different_base.sol b/test/libsolidity/syntaxTests/array/invalidCopy/storage_to_storage_different_base.sol new file mode 100644 index 000000000..b9f158697 --- /dev/null +++ b/test/libsolidity/syntaxTests/array/invalidCopy/storage_to_storage_different_base.sol @@ -0,0 +1,9 @@ +contract C { + byte[32] data1; + bytes2[10] data2; + function f() external { + data1 = data2; + } +} +// ---- +// TypeError 7407: (99-104): Type bytes2[10] storage ref is not implicitly convertible to expected type bytes1[32] storage ref. diff --git a/test/libsolidity/syntaxTests/array/invalidCopy/storage_to_storage_different_base_2.sol b/test/libsolidity/syntaxTests/array/invalidCopy/storage_to_storage_different_base_2.sol new file mode 100644 index 000000000..dabeb18e0 --- /dev/null +++ b/test/libsolidity/syntaxTests/array/invalidCopy/storage_to_storage_different_base_2.sol @@ -0,0 +1,9 @@ +contract C { + uint64[32] data1; + uint256[10] data2; + function f() external { + data1 = data2; + } +} +// ---- +// TypeError 7407: (102-107): Type uint256[10] storage ref is not implicitly convertible to expected type uint64[32] storage ref. diff --git a/test/libsolidity/syntaxTests/array/invalidCopy/storage_to_storage_dynamic_to_static.sol b/test/libsolidity/syntaxTests/array/invalidCopy/storage_to_storage_dynamic_to_static.sol new file mode 100644 index 000000000..1b3733a0b --- /dev/null +++ b/test/libsolidity/syntaxTests/array/invalidCopy/storage_to_storage_dynamic_to_static.sol @@ -0,0 +1,9 @@ +contract C { + uint256[10] data1; + uint256[] data2; + function f() external { + data1 = data2; + } +} +// ---- +// TypeError 7407: (101-106): Type uint256[] storage ref is not implicitly convertible to expected type uint256[10] storage ref. diff --git a/test/libsolidity/syntaxTests/array/invalidCopy/storage_to_storage_static_longer_to_shorter.sol b/test/libsolidity/syntaxTests/array/invalidCopy/storage_to_storage_static_longer_to_shorter.sol new file mode 100644 index 000000000..95185d317 --- /dev/null +++ b/test/libsolidity/syntaxTests/array/invalidCopy/storage_to_storage_static_longer_to_shorter.sol @@ -0,0 +1,9 @@ +contract C { + uint256[10] data1; + uint256[18] data2; + function f() external { + data1 = data2; + } +} +// ---- +// TypeError 7407: (103-108): Type uint256[18] storage ref is not implicitly convertible to expected type uint256[10] storage ref.