Merge pull request #13299 from ethereum/fix-bad-cast-tuple-returned-from-function-abi-encodeCall

Fix bad_cast when abi.encodeCall() receives a tuple expression
This commit is contained in:
Kamil Śliwak 2022-08-04 16:00:47 +02:00 committed by GitHub
commit c9f772eba8
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
18 changed files with 250 additions and 2 deletions

View File

@ -13,6 +13,7 @@ Compiler Features:
Bugfixes:
* Commandline Interface: Disallow the following options outside of the compiler mode: ``--via-ir``,``--metadata-literal``, ``--metadata-hash``, ``--model-checker-show-unproved``, ``--model-checker-div-mod-no-slacks``, ``--model-checker-engine``, ``--model-checker-invariants``, ``--model-checker-solvers``, ``--model-checker-timeout``, ``--model-checker-contracts``, ``--model-checker-targets``.
* Type Checker: Fix null dereference in `abi.encodeCall` type checking of free function.
* Type Checker: Fix compiler crash when `abi.encodeCall` received a tuple expression instead of an inline tuple.
### 0.8.15 (2022-06-15)

View File

@ -2248,8 +2248,17 @@ void TypeChecker::typeCheckABIEncodeCallFunction(FunctionCall const& _functionCa
auto const* tupleType = dynamic_cast<TupleType const*>(type(*arguments[1]));
if (tupleType)
{
auto const& argumentTuple = dynamic_cast<TupleExpression const&>(*arguments[1].get());
callArguments = decltype(callArguments){argumentTuple.components().begin(), argumentTuple.components().end()};
if (TupleExpression const* argumentTuple = dynamic_cast<TupleExpression const*>(arguments[1].get()))
callArguments = decltype(callArguments){argumentTuple->components().begin(), argumentTuple->components().end()};
else
{
m_errorReporter.typeError(
9062_error,
arguments[1]->location(),
"Expected an inline tuple, not an expression of a tuple type."
);
return;
}
}
else
callArguments.push_back(arguments[1]);

View File

@ -0,0 +1,24 @@
contract C {
function g0() internal pure {}
function g2() internal pure returns (uint, uint) { return (2, 3); }
function f0() public {}
function f2(uint, uint) public {}
function h() public view {
uint a;
uint b;
abi.encodeCall(this.f0, () = g0());
abi.encodeCall(this.f0, () = ());
abi.encodeCall(this.f2, (a, b) = g2());
abi.encodeCall(this.f2, (a, b) = (2, 3));
}
}
// ----
// TypeError 5547: (284-286): Empty tuple on the left hand side.
// TypeError 9062: (284-293): Expected an inline tuple, not an expression of a tuple type.
// TypeError 5547: (328-330): Empty tuple on the left hand side.
// TypeError 9062: (328-335): Expected an inline tuple, not an expression of a tuple type.
// TypeError 9062: (370-383): Expected an inline tuple, not an expression of a tuple type.
// TypeError 9062: (418-433): Expected an inline tuple, not an expression of a tuple type.

View File

@ -0,0 +1,17 @@
contract C {
function g0() internal pure {}
function g2() internal pure returns (uint, uint) { return (2, 3); }
function f0() public {}
function f2(uint, uint) public {}
function h() public view {
abi.encodeCall(this.f0, true ? g0() : g0());
abi.encodeCall(this.f2, true ? g2() : g2());
abi.encodeCall(this.f2, true ? (1, 2) : (3, 4));
}
}
// ----
// TypeError 9062: (251-269): Expected an inline tuple, not an expression of a tuple type.
// TypeError 9062: (304-322): Expected an inline tuple, not an expression of a tuple type.
// TypeError 9062: (357-379): Expected an inline tuple, not an expression of a tuple type.

View File

@ -0,0 +1,16 @@
contract C {
event Ev();
error Er();
function f0() public {}
function h() public view {
abi.encodeCall(this.f0, Ev());
abi.encodeCall(this.f0, Er());
abi.encodeCall(this.f0, revert());
}
}
// ----
// TypeError 9062: (138-142): Expected an inline tuple, not an expression of a tuple type.
// TypeError 9062: (177-181): Expected an inline tuple, not an expression of a tuple type.
// TypeError 9062: (216-224): Expected an inline tuple, not an expression of a tuple type.

View File

@ -0,0 +1,23 @@
contract C {
event Ev();
error Er();
function g0() internal pure {}
function g2() internal pure returns (uint, uint) { return (2, 3); }
function f0() public {}
function f2(uint, uint) public {}
function h() public view {
abi.encodeCall(this.f2, (1, 1) + (2, 2));
abi.encodeCall(this.f0, Ev() / Er());
abi.encodeCall(this.f0, !());
}
}
// ----
// TypeError 2271: (284-299): Operator + not compatible with types tuple(int_const 1,int_const 1) and tuple(int_const 2,int_const 2)
// TypeError 9062: (284-299): Expected an inline tuple, not an expression of a tuple type.
// TypeError 2271: (334-345): Operator / not compatible with types tuple() and tuple()
// TypeError 9062: (334-345): Expected an inline tuple, not an expression of a tuple type.
// TypeError 4907: (380-383): Unary operator ! cannot be applied to type tuple()
// TypeError 9062: (380-383): Expected an inline tuple, not an expression of a tuple type.

View File

@ -0,0 +1,22 @@
contract C {
function g0() internal pure {}
function g2() internal pure returns (uint, uint) { return (2, 3); }
function f0() public {}
function f2(uint, uint) public {}
function h() public view {
abi.encodeCall(this.f0, g0());
abi.encodeCall(this.f2, g2());
abi.encodeCall(this.f0, (g0()));
abi.encodeCall(this.f2, (g2()));
}
}
// ----
// TypeError 9062: (251-255): Expected an inline tuple, not an expression of a tuple type.
// TypeError 9062: (290-294): Expected an inline tuple, not an expression of a tuple type.
// TypeError 6473: (331-335): Tuple component cannot be empty.
// TypeError 7788: (306-337): Expected 0 instead of 1 components for the tuple parameter.
// TypeError 7788: (347-378): Expected 2 instead of 1 components for the tuple parameter.
// TypeError 5407: (372-376): Cannot implicitly convert component at position 0 from "tuple(uint256,uint256)" to "uint256".

View File

@ -0,0 +1,13 @@
contract C {
function g1() internal pure returns (uint) { return (1); }
function f1(uint) public {}
function h() public view {
uint a;
abi.encodeCall(this.f1, (a) = g1());
abi.encodeCall(this.f1, (a) = (1));
}
}
// ----

View File

@ -0,0 +1,11 @@
contract C {
function g1() internal pure returns (uint) { return (1); }
function f1(uint) public {}
function h() public view {
abi.encodeCall(this.f1, true ? (1) : (2));
abi.encodeCall(this.f1, true ? g1() : g1());
}
}
// ----

View File

@ -0,0 +1,14 @@
contract C {
function g1() internal pure returns (uint) { return (1); }
function g2() internal pure returns (uint, uint) { return (2, 3); }
function f1(uint) public {}
function f2(uint, uint) public {}
function h() public view {
abi.encodeCall(this.f1, g1());
abi.encodeCall(this.f1, (g1()));
abi.encodeCall(this.f2, (g1(), g1()));
}
}
// ----

View File

@ -0,0 +1,15 @@
contract C {
function g0() internal pure {}
function g1() internal pure returns (uint) { return (1); }
function g2() internal pure returns (uint, uint) { return (2, 3); }
function h() public pure {
abi.encodePacked(g0());
abi.encodePacked(g2());
abi.encodePacked((g1(), g1()));
}
}
// ----
// TypeError 2056: (240-244): This type cannot be encoded.
// TypeError 2056: (272-276): This type cannot be encoded.
// TypeError 2056: (304-316): This type cannot be encoded.

View File

@ -0,0 +1,8 @@
contract C {
function g1() internal pure returns (uint) { return (1); }
function h() public pure {
abi.encodePacked(g1());
}
}
// ----

View File

@ -0,0 +1,19 @@
contract C {
function g0() internal pure {}
function g1() internal pure returns (uint) { return (1); }
function g2() internal pure returns (uint, uint) { return (2, 3); }
function f0() public {}
function f1(uint) public {}
function f2(uint, uint) public {}
function h() public pure {
abi.encodeWithSelector(this.f0.selector, g0());
abi.encodeWithSelector(this.f0.selector, g2());
abi.encodeWithSelector(this.f0.selector, (g1(), g1()));
}
}
// ----
// TypeError 2056: (363-367): This type cannot be encoded.
// TypeError 2056: (419-423): This type cannot be encoded.
// TypeError 2056: (475-487): This type cannot be encoded.

View File

@ -0,0 +1,10 @@
contract C {
function g1() internal pure returns (uint) { return (1); }
function f0() public {}
function h() public pure {
abi.encodeWithSelector(this.f0.selector, g1());
}
}
// ----

View File

@ -0,0 +1,15 @@
contract C {
function g0() internal pure {}
function g1() internal pure returns (uint) { return (1); }
function g2() internal pure returns (uint, uint) { return (2, 3); }
function h() public pure {
abi.encodeWithSignature("f0()", g0());
abi.encodeWithSignature("f()", g2());
abi.encodeWithSignature("f()", (g1(), g1()));
}
}
// ----
// TypeError 2056: (255-259): This type cannot be encoded.
// TypeError 2056: (301-305): This type cannot be encoded.
// TypeError 2056: (347-359): This type cannot be encoded.

View File

@ -0,0 +1,8 @@
contract C {
function g1() internal pure returns (uint) { return (1); }
function h() public pure {
abi.encodeWithSignature("f()", g1());
}
}
// ----

View File

@ -0,0 +1,15 @@
contract C {
function g0() internal pure {}
function g1() internal pure returns (uint) { return (1); }
function g2() internal pure returns (uint, uint) { return (2, 3); }
function h() public pure {
abi.encode(g0());
abi.encode(g2());
abi.encode((g1(), g1()));
}
}
// ----
// TypeError 2056: (234-238): This type cannot be encoded.
// TypeError 2056: (260-264): This type cannot be encoded.
// TypeError 2056: (286-298): This type cannot be encoded.

View File

@ -0,0 +1,8 @@
contract C {
function g1() internal pure returns (uint) { return (1); }
function h() public pure {
abi.encode(g1());
}
}
// ----