Restrict mobile types of function types.

Move ternary tests to semanticTests
This commit is contained in:
Daniel Kirchner 2023-06-26 19:07:24 +02:00 committed by Nikola Matic
parent 2c82873a2c
commit 110e2a656d
16 changed files with 153 additions and 37 deletions

View File

@ -30,6 +30,7 @@ Bugfixes:
* SMTChecker: Fix false negative when a verification target can be violated only by trusted external call from another public function. * SMTChecker: Fix false negative when a verification target can be violated only by trusted external call from another public function.
* SMTChecker: Fix internal error caused by using external identifier to encode member access to functions that take an internal function as a parameter. * SMTChecker: Fix internal error caused by using external identifier to encode member access to functions that take an internal function as a parameter.
* Standard JSON Interface: Fix an incomplete AST being returned when analysis is interrupted by certain kinds of fatal errors. * Standard JSON Interface: Fix an incomplete AST being returned when analysis is interrupted by certain kinds of fatal errors.
* Type Checker: Disallow using certain unassignable function types in complex expressions.
* Type Checker: Function declaration types referring to different declarations are no longer convertible to each other. * Type Checker: Function declaration types referring to different declarations are no longer convertible to each other.
* Yul Optimizer: Ensure that the assignment of memory slots for variables moved to memory does not depend on AST IDs that may depend on whether additional files are included during compilation. * Yul Optimizer: Ensure that the assignment of memory slots for variables moved to memory does not depend on AST IDs that may depend on whether additional files are included during compilation.
* Yul Optimizer: Fix ``FullInliner`` step not ignoring code that is not in expression-split form. * Yul Optimizer: Fix ``FullInliner`` step not ignoring code that is not in expression-split form.

View File

@ -3472,7 +3472,11 @@ Type const* FunctionType::mobileType() const
if (valueSet() || gasSet() || saltSet() || hasBoundFirstArgument()) if (valueSet() || gasSet() || saltSet() || hasBoundFirstArgument())
return nullptr; return nullptr;
// return function without parameter names // Special function types do not get a mobile type, such that they cannot be used in complex expressions.
if (m_kind != FunctionType::Kind::Internal && m_kind != FunctionType::Kind::External && m_kind != FunctionType::Kind::DelegateCall)
return nullptr;
// return function without parameter names and without declaration
return TypeProvider::function( return TypeProvider::function(
m_parameterTypes, m_parameterTypes,
m_returnParameterTypes, m_returnParameterTypes,
@ -3480,7 +3484,7 @@ Type const* FunctionType::mobileType() const
strings(m_returnParameterNames.size()), strings(m_returnParameterNames.size()),
m_kind, m_kind,
m_stateMutability, m_stateMutability,
m_declaration, nullptr,
Options::fromFunctionType(*this) Options::fromFunctionType(*this)
); );
} }

View File

@ -0,0 +1,10 @@
contract C {
function f() public {}
function g() public {}
function h(bool c) public returns (bytes4) {
return (c ? this.f : this.g).selector;
}
}
// ----
// h(bool): true -> 0x26121ff000000000000000000000000000000000000000000000000000000000
// h(bool): false -> 0xe2179b8e00000000000000000000000000000000000000000000000000000000

View File

@ -0,0 +1,19 @@
contract A {
function f() public {}
function g() public {}
}
contract C {
A a = new A();
function getContract() public view returns (A) {
return a;
}
function test(bool b) public view returns (bytes4) {
return (b ? getContract().f : getContract().g).selector;
}
}
// ----
// test(bool): true -> 0x26121ff000000000000000000000000000000000000000000000000000000000
// test(bool): false -> 0xe2179b8e00000000000000000000000000000000000000000000000000000000

View File

@ -0,0 +1,10 @@
contract C {
function f() internal pure returns(uint256) { return 1;}
function g() internal pure returns(uint256) { return 2; }
function test(bool b) public returns(uint256) {
return (b ? C.f : C.g)();
}
}
// ----
// test(bool): true -> 1
// test(bool): false -> 2

View File

@ -0,0 +1,13 @@
library L {
function f() internal pure returns(uint256){ return 1; }
}
contract C {
function g() internal pure returns(uint256) { return 2; }
function test(bool b) public returns(uint256) {
return (b ? L.f : C.g)();
}
}
// ----
// test(bool): true -> 1
// test(bool): false -> 2

View File

@ -0,0 +1,10 @@
contract C {
function f() public pure returns(uint256) { return 1; }
function g() public pure returns(uint256) { return 2; }
function test(bool b) public returns(uint256) {
return (b ? C.f : C.g)();
}
}
// ----
// test(bool): true -> 1
// test(bool): false -> 2

View File

@ -0,0 +1,11 @@
error MyCustomError(uint, bool);
contract C {
function f() pure public {
true ? MyCustomError : MyCustomError;
}
}
// ----
// TypeError 9717: (93-106): Invalid mobile type in true expression.
// TypeError 3703: (109-122): Invalid mobile type in false expression.

View File

@ -1,18 +0,0 @@
error MyCustomError(uint, bool);
error MyCustomError2(uint, bool);
error MyCustomError3(uint, bool, bool);
contract C {
function f() pure public {
true ? MyCustomError : MyCustomError;
true ? MyCustomError : MyCustomError2;
true ? MyCustomError : MyCustomError3;
true ? MyCustomError : true;
true ? true : MyCustomError;
}
}
// ----
// TypeError 1080: (253-290): True expression's type error MyCustomError(uint256,bool) does not match false expression's type error MyCustomError3(uint256,bool,bool).
// TypeError 1080: (300-327): True expression's type error MyCustomError(uint256,bool) does not match false expression's type bool.
// TypeError 1080: (337-364): True expression's type bool does not match false expression's type error MyCustomError(uint256,bool).

View File

@ -0,0 +1,10 @@
contract C {
event MyCustomEvent(uint);
function f() pure public {
true ? MyCustomEvent : MyCustomEvent;
}
}
// ----
// TypeError 9717: (90-103): Invalid mobile type in true expression.
// TypeError 3703: (106-119): Invalid mobile type in false expression.

View File

@ -1,17 +0,0 @@
contract C {
event MyCustomEvent(uint);
event MyCustomEvent2(uint);
event MyCustomEvent3(uint, bool);
function f() pure public {
true ? MyCustomEvent : MyCustomEvent;
true ? MyCustomEvent : MyCustomEvent2;
true ? MyCustomEvent : MyCustomEvent3;
true ? MyCustomEvent : true;
true ? true : MyCustomEvent;
}
}
// ----
// TypeError 1080: (246-283): True expression's type event MyCustomEvent(uint256) does not match false expression's type event MyCustomEvent3(uint256,bool).
// TypeError 1080: (293-320): True expression's type event MyCustomEvent(uint256) does not match false expression's type bool.
// TypeError 1080: (330-357): True expression's type bool does not match false expression's type event MyCustomEvent(uint256).

View File

@ -0,0 +1,8 @@
contract C {
function f() public pure returns (uint x) {
x = (true ? addmod : addmod)(3, 4, 5);
}
}
// ----
// TypeError 9717: (81-87): Invalid mobile type in true expression.
// TypeError 3703: (90-96): Invalid mobile type in false expression.

View File

@ -0,0 +1,10 @@
contract C {
function f() external pure { }
function g() external pure { }
function test(bool b) public returns(bytes4) {
(b ? C.f : C.g).selector;
}
}
// ----
// TypeError 9717: (147-150): Invalid mobile type in true expression.
// TypeError 3703: (153-156): Invalid mobile type in false expression.

View File

@ -0,0 +1,13 @@
contract C {
function f() public pure { }
function g() public pure { }
}
contract A {
function test(bool b) public returns(bytes4) {
(b ? C.f : C.g).selector;
}
}
// ----
// TypeError 9717: (159-162): Invalid mobile type in true expression.
// TypeError 3703: (165-168): Invalid mobile type in false expression.

View File

@ -0,0 +1,16 @@
contract C {
function f() external pure { }
}
contract D {
function g() external pure { }
}
contract A {
function test(bool b) public returns(bytes4) {
(b ? C.f : D.g).selector;
}
}
// ----
// TypeError 9717: (179-182): Invalid mobile type in true expression.
// TypeError 3703: (185-188): Invalid mobile type in false expression.

View File

@ -0,0 +1,16 @@
interface I1 {
function f() external pure;
}
interface I2 {
function g() external pure;
}
contract C {
function test(bool b) public returns(bytes4) {
(b ? I1.f : I2.g).selector;
}
}
// ----
// TypeError 9717: (177-181): Invalid mobile type in true expression.
// TypeError 3703: (184-188): Invalid mobile type in false expression.