Merge pull request #6958 from sifmelcara/fix-abiencoderv2-codegen

Fix incorrect abi encoding of storage array of data type that occupy multiple storage slots
This commit is contained in:
chriseth 2019-06-20 13:08:42 +02:00 committed by GitHub
commit 9bb7160c4c
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
7 changed files with 81 additions and 12 deletions

View File

@ -1,5 +1,9 @@
### 0.5.10 (unreleased)
Important Bugfixes:
* Fix incorrect abi encoding of storage array of data type that occupy multiple storage slots
Language Features:

View File

@ -1,4 +1,15 @@
[
{
"name": "ABIEncoderV2StorageArrayWithMultiSlotElement",
"summary": "Storage arrays containing structs or other arrays are not read properly when directly encoded in function calls or in abi.encode*.",
"description": "When storage arrays whose elements occupy more than a single storage slot are directly encoded in function calls or using abi.encode*, their elements are read in an overlapping manner, i.e. the element pointer is not properly advanced between reads. This is not a problem when the storage data is first copied to a memory variable.",
"introduced": "0.4.16",
"fixed": "0.5.10",
"severity": "low",
"conditions": {
"ABIEncoderV2": true
}
},
{
"name": "DynamicConstructorArgumentsClippedABIV2",
"summary": "A contract's constructor that takes structs or arrays that contain dynamically-sized arrays reverts or decodes to invalid data.",

View File

@ -452,6 +452,7 @@
},
"0.4.16": {
"bugs": [
"ABIEncoderV2StorageArrayWithMultiSlotElement",
"DynamicConstructorArgumentsClippedABIV2",
"UninitializedFunctionPointerInConstructor_0.4.x",
"IncorrectEventSignatureInLibraries_0.4.x",
@ -463,6 +464,7 @@
},
"0.4.17": {
"bugs": [
"ABIEncoderV2StorageArrayWithMultiSlotElement",
"DynamicConstructorArgumentsClippedABIV2",
"UninitializedFunctionPointerInConstructor_0.4.x",
"IncorrectEventSignatureInLibraries_0.4.x",
@ -475,6 +477,7 @@
},
"0.4.18": {
"bugs": [
"ABIEncoderV2StorageArrayWithMultiSlotElement",
"DynamicConstructorArgumentsClippedABIV2",
"UninitializedFunctionPointerInConstructor_0.4.x",
"IncorrectEventSignatureInLibraries_0.4.x",
@ -486,6 +489,7 @@
},
"0.4.19": {
"bugs": [
"ABIEncoderV2StorageArrayWithMultiSlotElement",
"DynamicConstructorArgumentsClippedABIV2",
"UninitializedFunctionPointerInConstructor_0.4.x",
"IncorrectEventSignatureInLibraries_0.4.x",
@ -514,6 +518,7 @@
},
"0.4.20": {
"bugs": [
"ABIEncoderV2StorageArrayWithMultiSlotElement",
"DynamicConstructorArgumentsClippedABIV2",
"UninitializedFunctionPointerInConstructor_0.4.x",
"IncorrectEventSignatureInLibraries_0.4.x",
@ -526,6 +531,7 @@
},
"0.4.21": {
"bugs": [
"ABIEncoderV2StorageArrayWithMultiSlotElement",
"DynamicConstructorArgumentsClippedABIV2",
"UninitializedFunctionPointerInConstructor_0.4.x",
"IncorrectEventSignatureInLibraries_0.4.x",
@ -538,6 +544,7 @@
},
"0.4.22": {
"bugs": [
"ABIEncoderV2StorageArrayWithMultiSlotElement",
"DynamicConstructorArgumentsClippedABIV2",
"UninitializedFunctionPointerInConstructor_0.4.x",
"IncorrectEventSignatureInLibraries_0.4.x",
@ -550,6 +557,7 @@
},
"0.4.23": {
"bugs": [
"ABIEncoderV2StorageArrayWithMultiSlotElement",
"DynamicConstructorArgumentsClippedABIV2",
"UninitializedFunctionPointerInConstructor_0.4.x",
"IncorrectEventSignatureInLibraries_0.4.x",
@ -561,6 +569,7 @@
},
"0.4.24": {
"bugs": [
"ABIEncoderV2StorageArrayWithMultiSlotElement",
"DynamicConstructorArgumentsClippedABIV2",
"UninitializedFunctionPointerInConstructor_0.4.x",
"IncorrectEventSignatureInLibraries_0.4.x",
@ -572,6 +581,7 @@
},
"0.4.25": {
"bugs": [
"ABIEncoderV2StorageArrayWithMultiSlotElement",
"DynamicConstructorArgumentsClippedABIV2",
"UninitializedFunctionPointerInConstructor_0.4.x",
"IncorrectEventSignatureInLibraries_0.4.x",
@ -581,6 +591,7 @@
},
"0.4.26": {
"bugs": [
"ABIEncoderV2StorageArrayWithMultiSlotElement",
"DynamicConstructorArgumentsClippedABIV2"
],
"released": "2019-04-29"
@ -689,6 +700,7 @@
},
"0.5.0": {
"bugs": [
"ABIEncoderV2StorageArrayWithMultiSlotElement",
"DynamicConstructorArgumentsClippedABIV2",
"UninitializedFunctionPointerInConstructor",
"IncorrectEventSignatureInLibraries",
@ -698,6 +710,7 @@
},
"0.5.1": {
"bugs": [
"ABIEncoderV2StorageArrayWithMultiSlotElement",
"DynamicConstructorArgumentsClippedABIV2",
"UninitializedFunctionPointerInConstructor",
"IncorrectEventSignatureInLibraries",
@ -707,6 +720,7 @@
},
"0.5.2": {
"bugs": [
"ABIEncoderV2StorageArrayWithMultiSlotElement",
"DynamicConstructorArgumentsClippedABIV2",
"UninitializedFunctionPointerInConstructor",
"IncorrectEventSignatureInLibraries",
@ -716,6 +730,7 @@
},
"0.5.3": {
"bugs": [
"ABIEncoderV2StorageArrayWithMultiSlotElement",
"DynamicConstructorArgumentsClippedABIV2",
"UninitializedFunctionPointerInConstructor",
"IncorrectEventSignatureInLibraries",
@ -725,6 +740,7 @@
},
"0.5.4": {
"bugs": [
"ABIEncoderV2StorageArrayWithMultiSlotElement",
"DynamicConstructorArgumentsClippedABIV2",
"UninitializedFunctionPointerInConstructor",
"IncorrectEventSignatureInLibraries",
@ -734,6 +750,7 @@
},
"0.5.5": {
"bugs": [
"ABIEncoderV2StorageArrayWithMultiSlotElement",
"DynamicConstructorArgumentsClippedABIV2",
"UninitializedFunctionPointerInConstructor",
"IncorrectEventSignatureInLibraries",
@ -745,6 +762,7 @@
},
"0.5.6": {
"bugs": [
"ABIEncoderV2StorageArrayWithMultiSlotElement",
"DynamicConstructorArgumentsClippedABIV2",
"UninitializedFunctionPointerInConstructor",
"IncorrectEventSignatureInLibraries",
@ -755,6 +773,7 @@
},
"0.5.7": {
"bugs": [
"ABIEncoderV2StorageArrayWithMultiSlotElement",
"DynamicConstructorArgumentsClippedABIV2",
"UninitializedFunctionPointerInConstructor",
"IncorrectEventSignatureInLibraries"
@ -763,12 +782,15 @@
},
"0.5.8": {
"bugs": [
"ABIEncoderV2StorageArrayWithMultiSlotElement",
"DynamicConstructorArgumentsClippedABIV2"
],
"released": "2019-04-30"
},
"0.5.9": {
"bugs": [],
"bugs": [
"ABIEncoderV2StorageArrayWithMultiSlotElement"
],
"released": "2019-05-28"
}
}

View File

@ -154,7 +154,7 @@ private:
EncodingOptions const& _options
);
/// Part of @a abiEncodingFunction for array target type and given memory array or
/// a given storage array with one item per slot.
/// a given storage array with every item occupies one or multiple full slots.
std::string abiEncodingFunctionSimpleArray(
ArrayType const& _givenType,
ArrayType const& _targetType,

View File

@ -737,18 +737,29 @@ string YulUtilFunctions::nextArrayElementFunction(ArrayType const& _type)
}
)");
templ("functionName", functionName);
if (_type.location() == DataLocation::Memory)
switch (_type.location())
{
case DataLocation::Memory:
templ("advance", "0x20");
else if (_type.location() == DataLocation::Storage)
templ("advance", "1");
else if (_type.location() == DataLocation::CallData)
templ("advance", toCompactHexWithPrefix(
break;
case DataLocation::Storage:
{
u256 size = _type.baseType()->storageSize();
solAssert(size >= 1, "");
templ("advance", toCompactHexWithPrefix(size));
break;
}
case DataLocation::CallData:
{
u256 size =
_type.baseType()->isDynamicallyEncoded() ?
32 :
_type.baseType()->calldataEncodedSize()
));
else
solAssert(false, "");
_type.baseType()->calldataEncodedSize();
solAssert(size >= 32 && size % 32 == 0, "");
templ("advance", toCompactHexWithPrefix(size));
break;
}
}
return templ.render();
});
}

View File

@ -141,7 +141,7 @@ public:
/// for the data position of an array which is stored in that slot / memory area / calldata area.
std::string arrayDataAreaFunction(ArrayType const& _type);
/// @returns the name of a function that advances an array data pointer to the next element.
/// Only works for memory arrays, calldata arrays and storage arrays that store one item per slot.
/// Only works for memory arrays, calldata arrays and storage arrays that every item occupies one or multiple full slots.
std::string nextArrayElementFunction(ArrayType const& _type);
/// @returns the name of a function that performs index access for mappings.

View File

@ -0,0 +1,21 @@
pragma experimental ABIEncoderV2;
// tests encoding from storage arrays
contract C {
uint256[2][] tmp_h;
function h(uint256[2][] calldata s) external returns (bytes memory) {
tmp_h = s;
return abi.encode(tmp_h);
}
uint256[2][2] tmp_i;
function i(uint256[2][2] calldata s) external returns (bytes memory) {
tmp_i = s;
return abi.encode(tmp_i);
}
}
// ====
// EVMVersion: >homestead
// ----
// h(uint256[2][]) : 0x20, 3, 123, 124, 223, 224, 323, 324 -> 32, 256, 0x20, 3, 123, 124, 223, 224, 323, 324
// i(uint256[2][2]): 123, 124, 223, 224 -> 32, 128, 123, 124, 223, 224