From 98e83303b104ff7a9c4b745afb171e5c6d838e13 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Kamil=20=C5=9Aliwak?= Date: Fri, 26 Feb 2021 14:08:03 +0100 Subject: [PATCH] Remove assertions preventing calldata->calldata conversion when cleanup is needed --- Changelog.md | 1 + libsolidity/codegen/CompilerUtils.cpp | 9 +++---- .../calldata/calldata_bound_bytes.sol | 20 +++++++++++++++ .../calldata_bound_dynamic_array_or_slice.sol | 25 +++++++++++++++++++ .../calldata/calldata_bound_static_array.sol | 20 +++++++++++++++ .../calldata/calldata_bound_struct.sol | 24 ++++++++++++++++++ .../calldata/calldata_struct.sol | 22 ++++++++++++++++ .../bound/bound_to_calldata_struct.sol | 15 +++++++++++ 8 files changed, 130 insertions(+), 6 deletions(-) create mode 100644 test/libsolidity/semanticTests/calldata/calldata_bound_bytes.sol create mode 100644 test/libsolidity/semanticTests/calldata/calldata_bound_dynamic_array_or_slice.sol create mode 100644 test/libsolidity/semanticTests/calldata/calldata_bound_static_array.sol create mode 100644 test/libsolidity/semanticTests/calldata/calldata_bound_struct.sol create mode 100644 test/libsolidity/semanticTests/calldata/calldata_struct.sol create mode 100644 test/libsolidity/syntaxTests/bound/bound_to_calldata_struct.sol diff --git a/Changelog.md b/Changelog.md index 7d0b7d3dd..28b61f7ac 100644 --- a/Changelog.md +++ b/Changelog.md @@ -7,6 +7,7 @@ Compiler Features: Bugfixes: + * Code Generator: Fix internal compiler error when calling functions bound to calldata structs and arrays. ### 0.8.6 (2021-06-22) diff --git a/libsolidity/codegen/CompilerUtils.cpp b/libsolidity/codegen/CompilerUtils.cpp index 08180be4e..9ae1741dd 100644 --- a/libsolidity/codegen/CompilerUtils.cpp +++ b/libsolidity/codegen/CompilerUtils.cpp @@ -1078,8 +1078,7 @@ void CompilerUtils::convertType( } case DataLocation::CallData: solAssert( - targetType.isByteArray() && - typeOnStack.isByteArray() && + ((targetType.isByteArray() && typeOnStack.isByteArray()) || _typeOnStack == _targetType) && typeOnStack.location() == DataLocation::CallData, "Invalid conversion to calldata type." ); @@ -1130,9 +1129,6 @@ void CompilerUtils::convertType( solAssert(targetTypeCategory == stackTypeCategory, ""); auto& targetType = dynamic_cast(_targetType); auto& typeOnStack = dynamic_cast(_typeOnStack); - solAssert( - targetType.location() != DataLocation::CallData - , ""); switch (targetType.location()) { case DataLocation::Storage: @@ -1208,7 +1204,8 @@ void CompilerUtils::convertType( } break; case DataLocation::CallData: - solAssert(false, "Invalid type conversion target location CallData."); + solAssert(_typeOnStack == _targetType, ""); + // nothing to do break; } break; diff --git a/test/libsolidity/semanticTests/calldata/calldata_bound_bytes.sol b/test/libsolidity/semanticTests/calldata/calldata_bound_bytes.sol new file mode 100644 index 000000000..44126a18f --- /dev/null +++ b/test/libsolidity/semanticTests/calldata/calldata_bound_bytes.sol @@ -0,0 +1,20 @@ +pragma abicoder v2; + +library L { + function reverse(bytes calldata _b) internal pure returns (bytes1, bytes1) { + return (_b[1], _b[0]); + } +} + +contract C { + using L for bytes; + + function test(uint, bytes calldata _b, uint) external pure returns (bytes1, bytes1) { + return _b.reverse(); + } +} + +// ==== +// compileViaYul: also +// ---- +// test(uint256,bytes,uint256): 7, 0x60, 4, 2, "ab" -> "b", "a" diff --git a/test/libsolidity/semanticTests/calldata/calldata_bound_dynamic_array_or_slice.sol b/test/libsolidity/semanticTests/calldata/calldata_bound_dynamic_array_or_slice.sol new file mode 100644 index 000000000..251910eae --- /dev/null +++ b/test/libsolidity/semanticTests/calldata/calldata_bound_dynamic_array_or_slice.sol @@ -0,0 +1,25 @@ +pragma abicoder v2; + +library L { + function reverse(uint[] calldata _a) internal pure returns (uint, uint) { + return (_a[1], _a[0]); + } +} + +contract C { + using L for *; + + function testArray(uint, uint[] calldata _a, uint) external pure returns (uint, uint) { + return _a.reverse(); + } + + function testSlice(uint, uint[] calldata _a, uint) external pure returns (uint, uint) { + return _a[:].reverse(); + } +} + +// ==== +// compileViaYul: also +// ---- +// testArray(uint256,uint256[],uint256): 7, 0x60, 4, 2, 66, 77 -> 77, 66 +// testSlice(uint256,uint256[],uint256): 7, 0x60, 4, 2, 66, 77 -> 77, 66 diff --git a/test/libsolidity/semanticTests/calldata/calldata_bound_static_array.sol b/test/libsolidity/semanticTests/calldata/calldata_bound_static_array.sol new file mode 100644 index 000000000..252c12579 --- /dev/null +++ b/test/libsolidity/semanticTests/calldata/calldata_bound_static_array.sol @@ -0,0 +1,20 @@ +pragma abicoder v2; + +library L { + function reverse(uint[2] calldata _a) internal pure returns (uint, uint) { + return (_a[1], _a[0]); + } +} + +contract C { + using L for uint[2]; + + function test(uint, uint[2] calldata _a, uint) external pure returns (uint, uint) { + return _a.reverse(); + } +} + +// ==== +// compileViaYul: also +// ---- +// test(uint256,uint256[2],uint256): 7, 66, 77, 4 -> 77, 66 diff --git a/test/libsolidity/semanticTests/calldata/calldata_bound_struct.sol b/test/libsolidity/semanticTests/calldata/calldata_bound_struct.sol new file mode 100644 index 000000000..2d599ac12 --- /dev/null +++ b/test/libsolidity/semanticTests/calldata/calldata_bound_struct.sol @@ -0,0 +1,24 @@ +pragma abicoder v2; + +struct S { + uint x; + uint y; +} + +library L { + function reverse(S calldata _s) internal pure returns (uint, uint) { + return (_s.y, _s.x); + } +} + +contract C { + using L for S; + + function test(uint, S calldata _s, uint) external pure returns (uint, uint) { + return _s.reverse(); + } +} +// ==== +// compileViaYul: also +// ---- +// test(uint256,(uint256,uint256),uint256): 7, 66, 77, 4 -> 77, 66 diff --git a/test/libsolidity/semanticTests/calldata/calldata_struct.sol b/test/libsolidity/semanticTests/calldata/calldata_struct.sol new file mode 100644 index 000000000..6eae8b0c5 --- /dev/null +++ b/test/libsolidity/semanticTests/calldata/calldata_struct.sol @@ -0,0 +1,22 @@ +pragma abicoder v2; + +struct S { + uint x; + uint y; +} + +library L { + function reverse(S calldata _s) internal pure returns (uint, uint) { + return (_s.y, _s.x); + } +} + +contract C { + function test(uint, S calldata _s, uint) external pure returns (uint, uint) { + return L.reverse(_s); + } +} +// ==== +// compileViaYul: also +// ---- +// test(uint256,(uint256,uint256),uint256): 7, 66, 77, 4 -> 77, 66 diff --git a/test/libsolidity/syntaxTests/bound/bound_to_calldata_struct.sol b/test/libsolidity/syntaxTests/bound/bound_to_calldata_struct.sol new file mode 100644 index 000000000..a03ffbe8c --- /dev/null +++ b/test/libsolidity/syntaxTests/bound/bound_to_calldata_struct.sol @@ -0,0 +1,15 @@ +struct S { + uint x; +} + +library L { + function f(S calldata) internal pure {} +} + +contract C { + using L for S; + + function run(S calldata _s) external pure { + _s.f(); + } +}