diff --git a/Changelog.md b/Changelog.md index f162a4d0a..4670f3ffb 100644 --- a/Changelog.md +++ b/Changelog.md @@ -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) diff --git a/libsolidity/analysis/TypeChecker.cpp b/libsolidity/analysis/TypeChecker.cpp index e2c8c52f7..6d872f240 100644 --- a/libsolidity/analysis/TypeChecker.cpp +++ b/libsolidity/analysis/TypeChecker.cpp @@ -2248,8 +2248,17 @@ void TypeChecker::typeCheckABIEncodeCallFunction(FunctionCall const& _functionCa auto const* tupleType = dynamic_cast(type(*arguments[1])); if (tupleType) { - auto const& argumentTuple = dynamic_cast(*arguments[1].get()); - callArguments = decltype(callArguments){argumentTuple.components().begin(), argumentTuple.components().end()}; + if (TupleExpression const* argumentTuple = dynamic_cast(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]); diff --git a/test/libsolidity/syntaxTests/abiEncoder/abi_encodeCall_tuple_from_assignment_expression.sol b/test/libsolidity/syntaxTests/abiEncoder/abi_encodeCall_tuple_from_assignment_expression.sol new file mode 100644 index 000000000..955cea06a --- /dev/null +++ b/test/libsolidity/syntaxTests/abiEncoder/abi_encodeCall_tuple_from_assignment_expression.sol @@ -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. diff --git a/test/libsolidity/syntaxTests/abiEncoder/abi_encodeCall_tuple_from_conditional_ternary_expression.sol b/test/libsolidity/syntaxTests/abiEncoder/abi_encodeCall_tuple_from_conditional_ternary_expression.sol new file mode 100644 index 000000000..3b8b549ba --- /dev/null +++ b/test/libsolidity/syntaxTests/abiEncoder/abi_encodeCall_tuple_from_conditional_ternary_expression.sol @@ -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. diff --git a/test/libsolidity/syntaxTests/abiEncoder/abi_encodeCall_tuple_from_error_event.sol b/test/libsolidity/syntaxTests/abiEncoder/abi_encodeCall_tuple_from_error_event.sol new file mode 100644 index 000000000..c96b82909 --- /dev/null +++ b/test/libsolidity/syntaxTests/abiEncoder/abi_encodeCall_tuple_from_error_event.sol @@ -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. diff --git a/test/libsolidity/syntaxTests/abiEncoder/abi_encodeCall_tuple_from_invalid_operator.sol b/test/libsolidity/syntaxTests/abiEncoder/abi_encodeCall_tuple_from_invalid_operator.sol new file mode 100644 index 000000000..1c9f63073 --- /dev/null +++ b/test/libsolidity/syntaxTests/abiEncoder/abi_encodeCall_tuple_from_invalid_operator.sol @@ -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. diff --git a/test/libsolidity/syntaxTests/abiEncoder/abi_encodeCall_tuple_returned_from_function.sol b/test/libsolidity/syntaxTests/abiEncoder/abi_encodeCall_tuple_returned_from_function.sol new file mode 100644 index 000000000..ddb4934c4 --- /dev/null +++ b/test/libsolidity/syntaxTests/abiEncoder/abi_encodeCall_tuple_returned_from_function.sol @@ -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". diff --git a/test/libsolidity/syntaxTests/abiEncoder/abi_encodeCall_unitary_tuple_from_assignment_expression.sol b/test/libsolidity/syntaxTests/abiEncoder/abi_encodeCall_unitary_tuple_from_assignment_expression.sol new file mode 100644 index 000000000..06bb65075 --- /dev/null +++ b/test/libsolidity/syntaxTests/abiEncoder/abi_encodeCall_unitary_tuple_from_assignment_expression.sol @@ -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)); + } +} +// ---- diff --git a/test/libsolidity/syntaxTests/abiEncoder/abi_encodeCall_unitary_tuple_from_conditional_ternary_expression.sol b/test/libsolidity/syntaxTests/abiEncoder/abi_encodeCall_unitary_tuple_from_conditional_ternary_expression.sol new file mode 100644 index 000000000..518d8d32f --- /dev/null +++ b/test/libsolidity/syntaxTests/abiEncoder/abi_encodeCall_unitary_tuple_from_conditional_ternary_expression.sol @@ -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()); + } +} +// ---- diff --git a/test/libsolidity/syntaxTests/abiEncoder/abi_encodeCall_unitary_tuple_returned_from_function.sol b/test/libsolidity/syntaxTests/abiEncoder/abi_encodeCall_unitary_tuple_returned_from_function.sol new file mode 100644 index 000000000..6308ce8f1 --- /dev/null +++ b/test/libsolidity/syntaxTests/abiEncoder/abi_encodeCall_unitary_tuple_returned_from_function.sol @@ -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())); + } +} +// ---- diff --git a/test/libsolidity/syntaxTests/specialFunctions/abi_encodePacked_tuple_returned_from_function.sol b/test/libsolidity/syntaxTests/specialFunctions/abi_encodePacked_tuple_returned_from_function.sol new file mode 100644 index 000000000..8dc796928 --- /dev/null +++ b/test/libsolidity/syntaxTests/specialFunctions/abi_encodePacked_tuple_returned_from_function.sol @@ -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. diff --git a/test/libsolidity/syntaxTests/specialFunctions/abi_encodePacked_unitary_tuple_returned_from_function.sol b/test/libsolidity/syntaxTests/specialFunctions/abi_encodePacked_unitary_tuple_returned_from_function.sol new file mode 100644 index 000000000..4ac1c1d40 --- /dev/null +++ b/test/libsolidity/syntaxTests/specialFunctions/abi_encodePacked_unitary_tuple_returned_from_function.sol @@ -0,0 +1,8 @@ +contract C { + function g1() internal pure returns (uint) { return (1); } + + function h() public pure { + abi.encodePacked(g1()); + } +} +// ---- diff --git a/test/libsolidity/syntaxTests/specialFunctions/abi_encodeWithSelector_tuple_returned_from_function.sol b/test/libsolidity/syntaxTests/specialFunctions/abi_encodeWithSelector_tuple_returned_from_function.sol new file mode 100644 index 000000000..b8d0bcfcb --- /dev/null +++ b/test/libsolidity/syntaxTests/specialFunctions/abi_encodeWithSelector_tuple_returned_from_function.sol @@ -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. diff --git a/test/libsolidity/syntaxTests/specialFunctions/abi_encodeWithSelector_unitary_tuple_returned_from_function.sol b/test/libsolidity/syntaxTests/specialFunctions/abi_encodeWithSelector_unitary_tuple_returned_from_function.sol new file mode 100644 index 000000000..1ef98b078 --- /dev/null +++ b/test/libsolidity/syntaxTests/specialFunctions/abi_encodeWithSelector_unitary_tuple_returned_from_function.sol @@ -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()); + } +} +// ---- diff --git a/test/libsolidity/syntaxTests/specialFunctions/abi_encodeWithSignature_tuple_returned_from_function.sol b/test/libsolidity/syntaxTests/specialFunctions/abi_encodeWithSignature_tuple_returned_from_function.sol new file mode 100644 index 000000000..c618ec1b2 --- /dev/null +++ b/test/libsolidity/syntaxTests/specialFunctions/abi_encodeWithSignature_tuple_returned_from_function.sol @@ -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. diff --git a/test/libsolidity/syntaxTests/specialFunctions/abi_encodeWithSignature_unitary_tuple_from_function.sol b/test/libsolidity/syntaxTests/specialFunctions/abi_encodeWithSignature_unitary_tuple_from_function.sol new file mode 100644 index 000000000..504871832 --- /dev/null +++ b/test/libsolidity/syntaxTests/specialFunctions/abi_encodeWithSignature_unitary_tuple_from_function.sol @@ -0,0 +1,8 @@ +contract C { + function g1() internal pure returns (uint) { return (1); } + + function h() public pure { + abi.encodeWithSignature("f()", g1()); + } +} +// ---- diff --git a/test/libsolidity/syntaxTests/specialFunctions/abi_encode_tuple_returned_from_function.sol b/test/libsolidity/syntaxTests/specialFunctions/abi_encode_tuple_returned_from_function.sol new file mode 100644 index 000000000..747ccdabf --- /dev/null +++ b/test/libsolidity/syntaxTests/specialFunctions/abi_encode_tuple_returned_from_function.sol @@ -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. diff --git a/test/libsolidity/syntaxTests/specialFunctions/abi_encode_unitary_tuple_returned_from_function.sol b/test/libsolidity/syntaxTests/specialFunctions/abi_encode_unitary_tuple_returned_from_function.sol new file mode 100644 index 000000000..6c3cdf84a --- /dev/null +++ b/test/libsolidity/syntaxTests/specialFunctions/abi_encode_unitary_tuple_returned_from_function.sol @@ -0,0 +1,8 @@ +contract C { + function g1() internal pure returns (uint) { return (1); } + + function h() public pure { + abi.encode(g1()); + } +} +// ----