Merge pull request #839 from chriseth/checkcode

BREAKING: Make function calls throw if target does not have code.
This commit is contained in:
chriseth 2016-08-17 16:44:15 +02:00 committed by GitHub
commit b2507e9f10
3 changed files with 37 additions and 0 deletions

View File

@ -69,6 +69,10 @@ this does not execute a constructor. We could also have used ``function setFeed(
only (locally) sets the value and amount of gas sent with the function call and only the only (locally) sets the value and amount of gas sent with the function call and only the
parentheses at the end perform the actual call. parentheses at the end perform the actual call.
Function calls cause exceptions if the called contract does not exist (in the
sense that the account does not contain code) or if the called contract itself
throws an exception or goes out of gas.
.. warning:: .. warning::
Any interaction with another contract imposes a potential danger, especially Any interaction with another contract imposes a potential danger, especially
if the source code of the contract is not known in advance. The current if the source code of the contract is not known in advance. The current

View File

@ -1524,6 +1524,13 @@ void ExpressionCompiler::appendExternalFunctionCall(
m_context << u256(0); m_context << u256(0);
m_context << dupInstruction(m_context.baseToCurrentStackOffset(contractStackPos)); m_context << dupInstruction(m_context.baseToCurrentStackOffset(contractStackPos));
// Check the the target contract exists (has code) for non-low-level calls.
if (funKind == FunctionKind::External || funKind == FunctionKind::CallCode || funKind == FunctionKind::DelegateCall)
{
m_context << Instruction::DUP1 << Instruction::EXTCODESIZE << Instruction::ISZERO;
m_context.appendConditionalJumpTo(m_context.errorTag());
}
if (_functionType.gasSet()) if (_functionType.gasSet())
m_context << dupInstruction(m_context.baseToCurrentStackOffset(gasStackPos)); m_context << dupInstruction(m_context.baseToCurrentStackOffset(gasStackPos));
else else

View File

@ -7049,6 +7049,32 @@ BOOST_AUTO_TEST_CASE(failing_ecrecover_invalid_input)
BOOST_CHECK(callContractFunction("f()") == encodeArgs(u256(0))); BOOST_CHECK(callContractFunction("f()") == encodeArgs(u256(0)));
} }
BOOST_AUTO_TEST_CASE(calling_nonexisting_contract_throws)
{
char const* sourceCode = R"(
contract D { function g(); }
contract C {
D d = D(0x1212);
function f() returns (uint) {
d.g();
return 7;
}
function g() returns (uint) {
d.g.gas(200)();
return 7;
}
function h() returns (uint) {
d.call(); // this does not throw (low-level)
return 7;
}
}
)";
compileAndRun(sourceCode, 0, "C");
BOOST_CHECK(callContractFunction("f()") == encodeArgs());
BOOST_CHECK(callContractFunction("g()") == encodeArgs());
BOOST_CHECK(callContractFunction("h()") == encodeArgs(u256(7)));
}
BOOST_AUTO_TEST_SUITE_END() BOOST_AUTO_TEST_SUITE_END()
} }