diff options
-rw-r--r-- | Changelog.md | 1 | ||||
-rw-r--r-- | libsolidity/ast/Types.cpp | 20 | ||||
-rw-r--r-- | test/libsolidity/syntaxTests/specialFunctions/encodePacked_array_of_structs.sol | 9 | ||||
-rw-r--r-- | test/libsolidity/syntaxTests/specialFunctions/encode_array_of_struct.sol | 10 |
4 files changed, 30 insertions, 10 deletions
diff --git a/Changelog.md b/Changelog.md index 732c0a7f..7cbdc764 100644 --- a/Changelog.md +++ b/Changelog.md @@ -98,6 +98,7 @@ Bugfixes: * References Resolver: Report error instead of assertion fail when FunctionType has an undeclared type as parameter. * Type Checker: Default data location for type conversions (e.g. from literals) is memory and not storage. * Type Checker: Disallow assignments to mappings within tuple assignments as well. + * Type Checker: Disallow packed encoding of arrays of structs. * Type Checker: Allow assignments to local variables of mapping types. * Type Checker: Consider fixed size arrays when checking for recursive structs. * Type Checker: Fix crashes in erroneous tuple assignments in which the type of the right hand side cannot be determined. diff --git a/libsolidity/ast/Types.cpp b/libsolidity/ast/Types.cpp index 349e4a02..0d69ae1a 100644 --- a/libsolidity/ast/Types.cpp +++ b/libsolidity/ast/Types.cpp @@ -394,17 +394,17 @@ TypePointer Type::fullEncodingType(bool _inLibraryCall, bool _encoderV2, bool _p encodingType = encodingType->interfaceType(_inLibraryCall); if (encodingType) encodingType = encodingType->encodingType(); - if (auto structType = dynamic_cast<StructType const*>(encodingType.get())) - { - // Structs are fine in the following circumstances: - // - ABIv2 without packed encoding or, - // - storage struct for a library - if (!( - (_encoderV2 && !_packed) || - (structType->location() == DataLocation::Storage && _inLibraryCall) - )) + // Structs are fine in the following circumstances: + // - ABIv2 without packed encoding or, + // - storage struct for a library + if (_inLibraryCall && encodingType->dataStoredIn(DataLocation::Storage)) + return encodingType; + TypePointer baseType = encodingType; + while (auto const* arrayType = dynamic_cast<ArrayType const*>(baseType.get())) + baseType = arrayType->baseType(); + if (dynamic_cast<StructType const*>(baseType.get())) + if (!_encoderV2 || _packed) return TypePointer(); - } return encodingType; } diff --git a/test/libsolidity/syntaxTests/specialFunctions/encodePacked_array_of_structs.sol b/test/libsolidity/syntaxTests/specialFunctions/encodePacked_array_of_structs.sol new file mode 100644 index 00000000..036e108a --- /dev/null +++ b/test/libsolidity/syntaxTests/specialFunctions/encodePacked_array_of_structs.sol @@ -0,0 +1,9 @@ +contract C { + struct S { uint x; } + function f() public pure { + S[] memory s; + abi.encodePacked(s); + } +} +// ---- +// TypeError: (116-117): This type cannot be encoded. diff --git a/test/libsolidity/syntaxTests/specialFunctions/encode_array_of_struct.sol b/test/libsolidity/syntaxTests/specialFunctions/encode_array_of_struct.sol new file mode 100644 index 00000000..7a4d8250 --- /dev/null +++ b/test/libsolidity/syntaxTests/specialFunctions/encode_array_of_struct.sol @@ -0,0 +1,10 @@ +pragma experimental ABIEncoderV2; +contract C { + struct S { uint x; } + function f() public pure { + S[] memory s; + abi.encode(s); + } +} +// ---- +// Warning: (0-33): Experimental features are turned on. Do not use experimental features on live deployments. |