Merge pull request #12372 from nishant-sachdeva/invalid_ir_generated_during_copy_of_dynamically_sized_storage_arrays_of_function_type

Added sameType check for fromType and toType in YulUtilFunctions.cpp and relevant tests in semanticTests
This commit is contained in:
chriseth 2021-12-15 20:05:46 +01:00 committed by GitHub
commit 1822261da1
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
6 changed files with 108 additions and 4 deletions

View File

@ -11,7 +11,7 @@ Bugfixes:
* SMTChecker: Fix internal error when an unsafe target is solved more than once and the counterexample messages are different.
* SMTChecker: Fix soundness of assigned storage/memory local pointers that were not erasing enough knowledge.
* Fix internal error when a function has a calldata struct argument with an internal type inside.
* IR Generator: Fix IR syntax error when copying storage arrays of functions.
### 0.8.10 (2021-11-09)

View File

@ -2057,7 +2057,7 @@ string YulUtilFunctions::copyValueArrayStorageToStorageFunction(ArrayType const&
solAssert(!_fromType.isValueType(), "");
templ("functionName", functionName);
templ("resizeArray", resizeArrayFunction(_toType));
templ("arrayLength",arrayLengthFunction(_fromType));
templ("arrayLength", arrayLengthFunction(_fromType));
templ("panic", panicFunction(PanicCode::ResourceError));
templ("srcDataLocation", arrayDataAreaFunction(_fromType));
templ("dstDataLocation", arrayDataAreaFunction(_toType));
@ -2065,7 +2065,14 @@ string YulUtilFunctions::copyValueArrayStorageToStorageFunction(ArrayType const&
unsigned itemsPerSlot = 32 / _toType.storageStride();
templ("itemsPerSlot", to_string(itemsPerSlot));
templ("multipleItemsPerSlotDst", itemsPerSlot > 1);
bool sameType = _fromType.baseType() == _toType.baseType();
bool sameType = *_fromType.baseType() == *_toType.baseType();
if (auto functionType = dynamic_cast<FunctionType const*>(_fromType.baseType()))
{
solAssert(functionType->equalExcludingStateMutability(
dynamic_cast<FunctionType const&>(*_toType.baseType())
));
sameType = true;
}
templ("sameType", sameType);
if (sameType)
{

View File

@ -0,0 +1,43 @@
contract C {
function testFunction1() public {}
function testFunction2() public {}
function testFunction3() public {}
function() external [3] externalArray0;
function() external [3] externalArray1 = [
this.testFunction1,
this.testFunction2,
this.testFunction3
];
function copyExternalStorageArrayOfFunctionType() external returns (bool) {
assert(keccak256(abi.encode(externalArray0)) != keccak256(abi.encode(externalArray1)));
externalArray0 = externalArray1;
return keccak256(abi.encode(externalArray0)) == keccak256(abi.encode(externalArray1));
}
function() internal [3] internalArray0;
function() internal [3] internalArray1 = [
testFunction1,
testFunction2,
testFunction3
];
function copyInternalArrayOfFunctionType() external returns (bool) {
internalArray0 = internalArray1;
assert(internalArray0.length == 3);
return
internalArray0.length == internalArray1.length &&
internalArray0[0] == internalArray1[0] &&
internalArray0[1] == internalArray1[1] &&
internalArray0[2] == internalArray1[2];
}
}
// ====
// compileViaYul: also
// ----
// copyExternalStorageArrayOfFunctionType() -> true
// gas legacy: 103412
// copyInternalArrayOfFunctionType() -> true

View File

@ -0,0 +1,45 @@
contract C {
function testFunction1() public {}
function testFunction2() public view {}
function testFunction3() public pure {}
function() external [3] externalArray0;
function() external [3] externalArray1 = [
this.testFunction1,
this.testFunction2,
this.testFunction3
];
function copyExternalStorageArraysOfFunctionType() external returns (bool)
{
assert(keccak256(abi.encodePacked(externalArray0)) != keccak256(abi.encodePacked(externalArray1)));
externalArray0 = externalArray1;
return keccak256(abi.encodePacked(externalArray0)) == keccak256(abi.encodePacked(externalArray1));
}
function() internal [3] internalArray0;
function() internal [3] internalArray1 = [
testFunction1,
testFunction2,
testFunction3
];
function copyInternalArrayOfFunctionType() external returns (bool)
{
internalArray0 = internalArray1;
assert(internalArray0.length == 3);
return
internalArray0.length == internalArray1.length &&
internalArray0[0] == internalArray1[0] &&
internalArray0[1] == internalArray1[1] &&
internalArray0[2] == internalArray1[2];
}
}
// ====
// compileViaYul: also
// ----
// copyExternalStorageArraysOfFunctionType() -> true
// gas legacy: 103398
// copyInternalArrayOfFunctionType() -> true
// gas legacy: 104178

View File

@ -18,6 +18,6 @@ contract C {
// compileViaYul: also
// ----
// test() -> 7
// gas irOptimized: 126552
// gas irOptimized: 124080
// gas legacy: 205196
// gas legacyOptimized: 204987

View File

@ -0,0 +1,9 @@
contract C {
function() external [] s0;
function() external view [] s1;
function copyStorageArrayOfFunctionType() public {
s1 = s0;
}
}
// ----
// TypeError 7407: (148-150): Type function () external[] storage ref is not implicitly convertible to expected type function () view external[] storage ref.