Merge pull request #949 from chriseth/fallbackReturn

Disallow fallback function to return values.
This commit is contained in:
chriseth 2016-08-26 10:11:34 +02:00 committed by GitHub
commit d209e65b1d
4 changed files with 23 additions and 10 deletions

View File

@ -425,7 +425,8 @@ Fallback Function
***************** *****************
A contract can have exactly one unnamed function. This function cannot have A contract can have exactly one unnamed function. This function cannot have
arguments and is executed on a call to the contract if none of the other arguments and cannot return anything.
It is executed on a call to the contract if none of the other
functions matches the given function identifier (or if no data was supplied at functions matches the given function identifier (or if no data was supplied at
all). all).

View File

@ -94,6 +94,8 @@ bool TypeChecker::visit(ContractDefinition const& _contract)
fallbackFunction = function; fallbackFunction = function;
if (!fallbackFunction->parameters().empty()) if (!fallbackFunction->parameters().empty())
typeError(fallbackFunction->parameterList().location(), "Fallback function cannot take parameters."); typeError(fallbackFunction->parameterList().location(), "Fallback function cannot take parameters.");
if (!fallbackFunction->returnParameters().empty())
typeError(fallbackFunction->returnParameterList()->location(), "Fallback function cannot return values.");
} }
} }
if (!function->isImplemented()) if (!function->isImplemented())

View File

@ -2529,13 +2529,13 @@ BOOST_AUTO_TEST_CASE(fallback_function)
char const* sourceCode = R"( char const* sourceCode = R"(
contract A { contract A {
uint data; uint data;
function() returns (uint r) { data = 1; return 2; } function() { data = 1; }
function getData() returns (uint r) { return data; } function getData() returns (uint r) { return data; }
} }
)"; )";
compileAndRun(sourceCode); compileAndRun(sourceCode);
BOOST_CHECK(callContractFunction("getData()") == encodeArgs(0)); BOOST_CHECK(callContractFunction("getData()") == encodeArgs(0));
BOOST_CHECK(callContractFunction("") == encodeArgs(2)); BOOST_CHECK(callContractFunction("") == encodeArgs());
BOOST_CHECK(callContractFunction("getData()") == encodeArgs(1)); BOOST_CHECK(callContractFunction("getData()") == encodeArgs(1));
} }
@ -2544,14 +2544,14 @@ BOOST_AUTO_TEST_CASE(inherited_fallback_function)
char const* sourceCode = R"( char const* sourceCode = R"(
contract A { contract A {
uint data; uint data;
function() returns (uint r) { data = 1; return 2; } function() { data = 1; }
function getData() returns (uint r) { return data; } function getData() returns (uint r) { return data; }
} }
contract B is A {} contract B is A {}
)"; )";
compileAndRun(sourceCode, 0, "B"); compileAndRun(sourceCode, 0, "B");
BOOST_CHECK(callContractFunction("getData()") == encodeArgs(0)); BOOST_CHECK(callContractFunction("getData()") == encodeArgs(0));
BOOST_CHECK(callContractFunction("") == encodeArgs(2)); BOOST_CHECK(callContractFunction("") == encodeArgs());
BOOST_CHECK(callContractFunction("getData()") == encodeArgs(1)); BOOST_CHECK(callContractFunction("getData()") == encodeArgs(1));
} }
@ -3002,13 +3002,13 @@ BOOST_AUTO_TEST_CASE(bytes_from_calldata_to_memory)
{ {
char const* sourceCode = R"( char const* sourceCode = R"(
contract C { contract C {
function() returns (bytes32) { function f() returns (bytes32) {
return sha3("abc", msg.data); return sha3("abc", msg.data);
} }
} }
)"; )";
compileAndRun(sourceCode); compileAndRun(sourceCode);
bytes calldata1 = bytes(61, 0x22) + bytes(12, 0x12); bytes calldata1 = FixedHash<4>(dev::sha3("f()")).asBytes() + bytes(61, 0x22) + bytes(12, 0x12);
sendMessage(calldata1, false); sendMessage(calldata1, false);
BOOST_CHECK(m_output == encodeArgs(dev::sha3(bytes{'a', 'b', 'c'} + calldata1))); BOOST_CHECK(m_output == encodeArgs(dev::sha3(bytes{'a', 'b', 'c'} + calldata1)));
} }
@ -3024,7 +3024,7 @@ BOOST_AUTO_TEST_CASE(call_forward_bytes)
contract sender { contract sender {
function sender() { rec = new receiver(); } function sender() { rec = new receiver(); }
function() { savedData = msg.data; } function() { savedData = msg.data; }
function forward() returns (bool) { rec.call(savedData); return true; } function forward() returns (bool) { !rec.call(savedData); return true; }
function clear() returns (bool) { delete savedData; return true; } function clear() returns (bool) { delete savedData; return true; }
function val() returns (uint) { return rec.received(); } function val() returns (uint) { return rec.received(); }
receiver rec; receiver rec;
@ -4342,12 +4342,12 @@ BOOST_AUTO_TEST_CASE(external_types_in_calls)
y = this.t1(C1(7)); y = this.t1(C1(7));
} }
function t1(C1 a) returns (C1) { return a; } function t1(C1 a) returns (C1) { return a; }
function() returns (C1) { return C1(9); } function t2() returns (C1) { return C1(9); }
} }
)"; )";
compileAndRun(sourceCode, 0, "C"); compileAndRun(sourceCode, 0, "C");
BOOST_CHECK(callContractFunction("test()") == encodeArgs(u256(9), u256(7))); BOOST_CHECK(callContractFunction("test()") == encodeArgs(u256(9), u256(7)));
BOOST_CHECK(callContractFunction("nonexisting") == encodeArgs(u256(9))); BOOST_CHECK(callContractFunction("t2()") == encodeArgs(u256(9)));
} }
BOOST_AUTO_TEST_CASE(proper_order_of_overwriting_of_attributes) BOOST_AUTO_TEST_CASE(proper_order_of_overwriting_of_attributes)

View File

@ -1102,6 +1102,16 @@ BOOST_AUTO_TEST_CASE(fallback_function_with_arguments)
BOOST_CHECK(expectError(text) == Error::Type::TypeError); BOOST_CHECK(expectError(text) == Error::Type::TypeError);
} }
BOOST_AUTO_TEST_CASE(fallback_function_with_return_parameters)
{
char const* text = R"(
contract C {
function() returns (uint) { }
}
)";
BOOST_CHECK(expectError(text) == Error::Type::TypeError);
}
BOOST_AUTO_TEST_CASE(fallback_function_twice) BOOST_AUTO_TEST_CASE(fallback_function_twice)
{ {
char const* text = R"( char const* text = R"(