Add missing checks for parameter compatibilty with ABIEncoderV1 in calls

This commit is contained in:
Kamil Śliwak 2020-09-17 15:03:49 +02:00
parent 25d408058b
commit 33ff79bf82
24 changed files with 503 additions and 0 deletions

View File

@ -11,6 +11,7 @@ Compiler Features:
Bugfixes:
* Type Checker: Fix internal compiler error when calling `.push(<arg>)` for a storage array with a nested mapping.
* Type Checker: Add missing checks for calls using types incompatible with ABIEncoderV1 in modules where ABIEncoderV2 is not enabled.
### 0.7.2 (2020-09-28)

View File

@ -2178,6 +2178,52 @@ void TypeChecker::typeCheckFunctionGeneralChecks(
m_errorReporter.typeError(errorId, paramArgMap[i]->location(), description);
}
}
TypePointers const& returnParameterTypes = _functionType->returnParameterTypes();
bool isLibraryCall = (_functionType->kind() == FunctionType::Kind::DelegateCall);
bool callRequiresABIEncoding =
// ABIEncode/ABIDecode calls not included because they should have been already validated
// at this point and they have variadic arguments so they need special handling.
_functionType->kind() == FunctionType::Kind::DelegateCall ||
_functionType->kind() == FunctionType::Kind::External ||
_functionType->kind() == FunctionType::Kind::Creation ||
_functionType->kind() == FunctionType::Kind::Event;
if (callRequiresABIEncoding && !experimentalFeatureActive(ExperimentalFeature::ABIEncoderV2))
{
solAssert(!isVariadic, "");
solAssert(parameterTypes.size() == arguments.size(), "");
solAssert(!_functionType->isBareCall(), "");
solAssert(*_functionCall.annotation().kind == FunctionCallKind::FunctionCall, "");
for (size_t i = 0; i < parameterTypes.size(); ++i)
{
solAssert(parameterTypes[i], "");
if (!typeSupportedByOldABIEncoder(*parameterTypes[i], isLibraryCall))
m_errorReporter.typeError(
2443_error,
paramArgMap[i]->location(),
"The type of this parameter, " + parameterTypes[i]->toString(true) + ", "
"is only supported in ABIEncoderV2. "
"Use \"pragma experimental ABIEncoderV2;\" to enable the feature."
);
}
for (size_t i = 0; i < returnParameterTypes.size(); ++i)
{
solAssert(returnParameterTypes[i], "");
if (!typeSupportedByOldABIEncoder(*returnParameterTypes[i], isLibraryCall))
m_errorReporter.typeError(
2428_error,
_functionCall.location(),
"The type of return parameter " + toString(i + 1) + ", " + returnParameterTypes[i]->toString(true) + ", "
"is only supported in ABIEncoderV2. "
"Use \"pragma experimental ABIEncoderV2;\" to enable the feature."
);
}
}
}
bool TypeChecker::visit(FunctionCall const& _functionCall)

View File

@ -0,0 +1,21 @@
==== Source: A ====
pragma experimental ABIEncoderV2;
library L {
struct Item {
uint x;
}
function set(Item storage _item) external view {}
}
==== Source: B ====
import "A";
contract Test {
L.Item item;
function foo() public view {
L.set(item);
}
}
// ----

View File

@ -0,0 +1,20 @@
==== Source: A ====
pragma experimental ABIEncoderV2;
contract C {
struct Item {
uint x;
}
constructor(Item memory _item) {}
}
==== Source: B ====
import "A";
contract Test {
function foo() public {
new C(C.Item(5));
}
}
// ----
// TypeError 2443: (B:71-80): The type of this parameter, struct C.Item, is only supported in ABIEncoderV2. Use "pragma experimental ABIEncoderV2;" to enable the feature.

View File

@ -0,0 +1,20 @@
==== Source: A ====
pragma experimental ABIEncoderV2;
contract C {
struct Item {
uint x;
}
function set(uint _x, string memory _y, Item memory _item, bool _z) external view {}
}
==== Source: B ====
import "A";
contract Test {
function foo() public view {
C(0x00).set({_item: C.Item(50), _z: false, _y: "abc", _x: 30});
}
}
// ----
// TypeError 2443: (B:90-100): The type of this parameter, struct C.Item, is only supported in ABIEncoderV2. Use "pragma experimental ABIEncoderV2;" to enable the feature.

View File

@ -0,0 +1,22 @@
==== Source: A ====
pragma experimental ABIEncoderV2;
contract C {
struct Item {
uint x;
}
function get(Item memory _item) external {}
}
==== Source: B ====
import "A";
contract Test {
function foo() public {
C c = new C();
function(C.Item memory) external ptr = c.get;
ptr(C.Item(5));
}
}
// ----
// TypeError 2443: (B:146-155): The type of this parameter, struct C.Item, is only supported in ABIEncoderV2. Use "pragma experimental ABIEncoderV2;" to enable the feature.

View File

@ -0,0 +1,16 @@
==== Source: A ====
pragma experimental ABIEncoderV2;
contract C {
function f() external view returns (string[] memory) {}
}
==== Source: B ====
import "A";
contract D {
function g() public view {
C(0x00).f();
}
}
// ----
// TypeError 2428: (B:65-76): The type of return parameter 1, string[], is only supported in ABIEncoderV2. Use "pragma experimental ABIEncoderV2;" to enable the feature.

View File

@ -0,0 +1,20 @@
==== Source: A ====
pragma experimental ABIEncoderV2;
contract C {
struct Item {
uint x;
}
function get() external view returns(Item memory) {}
}
==== Source: B ====
import "A";
contract Test {
function foo() public view {
C(0x00).get();
}
}
// ----
// TypeError 2428: (B:70-83): The type of return parameter 1, struct C.Item, is only supported in ABIEncoderV2. Use "pragma experimental ABIEncoderV2;" to enable the feature.

View File

@ -0,0 +1,20 @@
==== Source: A ====
pragma experimental ABIEncoderV2;
contract C {
struct Item {
uint[] y;
}
function get() external view returns(Item memory) {}
}
==== Source: B ====
import "A";
contract Test {
function foo() public view {
C(0x00).get();
}
}
// ----
// TypeError 2428: (B:70-83): The type of return parameter 1, struct C.Item, is only supported in ABIEncoderV2. Use "pragma experimental ABIEncoderV2;" to enable the feature.

View File

@ -0,0 +1,19 @@
==== Source: A ====
pragma experimental ABIEncoderV2;
library L {
struct Item {
uint x;
}
event E(Item _value);
}
==== Source: B ====
import "A";
contract Test {
function foo() public {
emit L.E(L.Item(42));
}
}
// ----
// TypeError 2443: (B:74-84): The type of this parameter, struct L.Item, is only supported in ABIEncoderV2. Use "pragma experimental ABIEncoderV2;" to enable the feature.

View File

@ -0,0 +1,21 @@
==== Source: A ====
pragma experimental ABIEncoderV2;
library L {
struct Item {
uint x;
}
function get(Item storage _item) external view {}
}
==== Source: B ====
import "A";
contract Test {
L.Item item;
function foo() public view {
L.get(item);
}
}
// ----

View File

@ -0,0 +1,20 @@
==== Source: A ====
pragma experimental ABIEncoderV2;
library L {
struct Item {
uint x;
}
function get() external view returns(Item memory) {}
}
==== Source: B ====
import "A";
contract Test {
function foo() public view {
L.get();
}
}
// ----
// TypeError 2428: (B:70-77): The type of return parameter 1, struct L.Item, is only supported in ABIEncoderV2. Use "pragma experimental ABIEncoderV2;" to enable the feature.

View File

@ -0,0 +1,13 @@
pragma experimental ABIEncoderV2;
contract C {
function get() public view returns (uint[][] memory) {}
function test() public view returns (bool) {
uint[][] memory x = this.get();
}
}
// ====
// EVMVersion: >=byzantium
// ----
// Warning 2072: (166-183): Unused local variable.

View File

@ -0,0 +1,13 @@
pragma experimental ABIEncoderV2;
contract C {
function get() public view returns (uint[][] memory) {}
function test() public view returns (bool) {
uint[][] memory x = this.get();
}
}
// ====
// EVMVersion: <byzantium
// ----
// TypeError 9574: (166-196): Type inaccessible dynamic type is not implicitly convertible to expected type uint256[] memory[] memory.

View File

@ -0,0 +1,21 @@
==== Source: A ====
pragma experimental ABIEncoderV2;
contract C {
struct Item {
uint x;
}
constructor(Item memory _item) {}
}
==== Source: B ====
pragma experimental ABIEncoderV2;
import "A";
contract Test {
function foo() public {
new C(C.Item(5));
}
}
// ----

View File

@ -0,0 +1,23 @@
==== Source: A ====
pragma experimental ABIEncoderV2;
contract C {
struct Item {
uint x;
}
function get(Item memory _item) external {}
}
==== Source: B ====
pragma experimental ABIEncoderV2;
import "A";
contract Test {
function foo() public {
C c = new C();
function(C.Item memory) external ptr = c.get;
ptr(C.Item(5));
}
}
// ----

View File

@ -0,0 +1,17 @@
==== Source: A ====
pragma experimental ABIEncoderV2;
contract C {
function f() external view returns (string[] memory) {}
}
==== Source: B ====
pragma experimental ABIEncoderV2;
import "A";
contract D {
function g() public view {
C(0x00).f();
}
}
// ----

View File

@ -0,0 +1,21 @@
==== Source: A ====
pragma experimental ABIEncoderV2;
contract C {
struct Item {
uint x;
}
function get() external view returns(Item memory) {}
}
==== Source: B ====
pragma experimental ABIEncoderV2;
import "A";
contract Test {
function foo() public view {
C(0x00).get();
}
}
// ----

View File

@ -0,0 +1,21 @@
==== Source: A ====
pragma experimental ABIEncoderV2;
contract C {
struct Item {
uint[] y;
}
function get() external view returns(Item memory) {}
}
==== Source: B ====
pragma experimental ABIEncoderV2;
import "A";
contract Test {
function foo() public view {
C(0x00).get();
}
}
// ----

View File

@ -0,0 +1,20 @@
==== Source: A ====
pragma experimental ABIEncoderV2;
library L {
struct Item {
uint x;
}
event E(Item _value);
}
==== Source: B ====
pragma experimental ABIEncoderV2;
import "A";
contract Test {
function foo() public {
emit L.E(L.Item(42));
}
}
// ----

View File

@ -0,0 +1,25 @@
==== Source: A ====
pragma experimental ABIEncoderV2;
library L {
struct Item {
uint x;
}
function get(Item memory _item) external {}
}
==== Source: B ====
pragma experimental ABIEncoderV2;
import "A";
contract Test {
function foo() public {
// NOTE: This test checks a case that is currently not possible (pointer to an external
// library function) but it might become possible in the future.
function(L.Item memory) external ptr = L.get;
ptr(L.Item(5));
}
}
// ----
// TypeError 9574: (B:269-313): Type function (struct L.Item memory) is not implicitly convertible to expected type function (struct L.Item memory) external.

View File

@ -0,0 +1,21 @@
==== Source: A ====
pragma experimental ABIEncoderV2;
library L {
struct Item {
uint x;
}
function get() external view returns(Item memory) {}
}
==== Source: B ====
pragma experimental ABIEncoderV2;
import "A";
contract Test {
function foo() public view {
L.get();
}
}
// ----

View File

@ -0,0 +1,30 @@
==== Source: A ====
pragma experimental ABIEncoderV2;
struct Data {
bool flag;
}
contract A {
function get() public view returns (Data memory) {}
}
==== Source: B ====
import "A";
contract B {
modifier validate() {
A(0x00).get();
_;
}
}
==== Source: C ====
import "B";
contract C is B {
function foo()
public
validate()
{}
}
// ----
// TypeError 2428: (B:60-73): The type of return parameter 1, struct Data, is only supported in ABIEncoderV2. Use "pragma experimental ABIEncoderV2;" to enable the feature.

View File

@ -0,0 +1,32 @@
==== Source: A ====
pragma experimental ABIEncoderV2;
struct Data {
bool flag;
}
contract A {
function get() public view returns (Data memory) {}
}
==== Source: B ====
import "A";
contract B {
modifier validate() {
A(0x00).get();
_;
}
}
==== Source: C ====
pragma experimental ABIEncoderV2;
import "B";
contract C is B {
function foo()
public
validate()
{}
}
// ----
// TypeError 2428: (B:60-73): The type of return parameter 1, struct Data, is only supported in ABIEncoderV2. Use "pragma experimental ABIEncoderV2;" to enable the feature.