Merge pull request #10959 from ethereum/assert-too-strict

Loosened up a really strict assert from ABIFunctions.cpp
This commit is contained in:
chriseth 2021-02-23 14:59:14 +01:00 committed by GitHub
commit 596e8dd9b6
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
4 changed files with 151 additions and 2 deletions

View File

@ -13,6 +13,7 @@ Bugfixes:
* Type Checker: Fix internal error when override specifier is not a contract.
* SMTChecker: Fix missing type constraints on block and transaction variables in the deployment phase.
* AST: Added ``referencedDeclaration`` for enum members.
* Code Generator: Fix internal error when functions are passed as parameters of other callables, when the function types can be implicitly converted, but not identical.
AST Changes:

View File

@ -1028,8 +1028,12 @@ string ABIFunctions::abiEncodingFunctionFunctionType(
EncodingOptions const& _options
)
{
solAssert(_from.kind() == FunctionType::Kind::External, "");
solAssert(_from == _to, "");
solAssert(
_from.kind() == FunctionType::Kind::External &&
_from.isImplicitlyConvertibleTo(_to) &&
_from.sizeOnStack() == _to.sizeOnStack(),
"Invalid function type conversion requested"
);
string functionName =
"abi_encode_" +
@ -1042,11 +1046,13 @@ string ABIFunctions::abiEncodingFunctionFunctionType(
return createFunction(functionName, [&]() {
return Whiskers(R"(
function <functionName>(addr, function_id, pos) {
addr, function_id := <convert>(addr, function_id)
mstore(pos, <combineExtFun>(addr, function_id))
}
)")
("functionName", functionName)
("combineExtFun", m_utils.combineExternalFunctionIdFunction())
("convert", m_utils.conversionFunction(_from, _to))
.render();
});
else

View File

@ -0,0 +1,59 @@
contract D {
constructor(function() external pure returns (uint) ) {
}
}
library L {
function f() public pure returns (uint) {
return 5;
}
}
contract C {
function f() public returns (uint r) {
// An assert used to fail if the function types are not exactly equal (pure, view) v/s
// default
// ok
new D(this.testPure);
// not okay
new D(this.testView);
// not okay
new D(this.testDefault);
// not okay
new D(this.testDifferentSignature);
// not okay
new D(gasleft);
// not okay
new D(L.f);
// not okay
new D(testInternalFunction);
// not okay
new D(this.testInternalFunction);
}
function testPure() public pure returns (uint) {
}
function testView() public view returns (uint) {
block.timestamp;
}
function testDefault() public returns (uint) {
selfdestruct(payable(address(this)));
}
function testDifferentSignature(uint a) public pure returns (uint) {
}
function testInternalFunction() internal pure returns (uint) {
return 10;
}
}
// ----
// TypeError 9553: (415-428): Invalid type for argument in function call. Invalid implicit conversion from function () view external returns (uint256) to function () pure external returns (uint256) requested.
// TypeError 9553: (465-481): Invalid type for argument in function call. Invalid implicit conversion from function () external returns (uint256) to function () pure external returns (uint256) requested.
// TypeError 9553: (518-545): Invalid type for argument in function call. Invalid implicit conversion from function (uint256) pure external returns (uint256) to function () pure external returns (uint256) requested.
// TypeError 9553: (582-589): Invalid type for argument in function call. Invalid implicit conversion from function () view returns (uint256) to function () pure external returns (uint256) requested. Special functions can not be converted to function types.
// TypeError 9553: (626-629): Invalid type for argument in function call. Invalid implicit conversion from function () pure returns (uint256) to function () pure external returns (uint256) requested. Special functions can not be converted to function types.
// TypeError 9553: (666-686): Invalid type for argument in function call. Invalid implicit conversion from function () pure returns (uint256) to function () pure external returns (uint256) requested. Special functions can not be converted to function types.
// TypeError 9582: (723-748): Member "testInternalFunction" not found or not visible after argument-dependent lookup in contract C.

View File

@ -0,0 +1,83 @@
contract D {
constructor(function() external returns (uint)) {
}
}
contract E {
function test(function() external returns(uint) f) public returns (uint) {
return f();
}
}
library L {
function test(function() external returns(uint) f) public returns (uint) {
return f();
}
}
contract C {
uint x;
// tests for usage as constructor parameter
function f() public {
// An assert used to fail in ABIFunction.cpp that the function types are not exactly equal
// that is pure or view v/s default even though they could be converted.
new D(this.testPure);
new D(this.testView);
new D(this.testDefault);
}
// tests for usage as contract function parameter
function g() public {
E e = E(address(0));
e.test(this.testPure);
e.test(this.testView);
e.test(this.testDefault);
}
// tests for usage as library function parameter
function h() public {
L.test(this.testPure);
L.test(this.testView);
L.test(this.testDefault);
}
// tests for usage as return parameter
function i() public view returns (function() external returns(uint)) {
uint value = block.number % 3;
if (value == 0) {
return this.testPure;
}
else if (value == 1) {
return this.testView;
}
else {
return this.testDefault;
}
}
modifier mod(function() external returns(uint) fun) {
if (fun() == 0) {
_;
}
}
// tests for usage as modifier parameter
function j(function() external pure returns(uint) fun) mod(fun) public {
}
function testPure() public pure returns (uint) {
return 0;
}
function testView() public view returns (uint) {
return x;
}
function testDefault() public returns (uint) {
x = 5;
return x;
}
}
// ----