aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--Changelog.md2
-rw-r--r--libsolidity/codegen/ContractCompiler.cpp11
-rw-r--r--test/libsolidity/SolidityEndToEndTest.cpp19
3 files changed, 25 insertions, 7 deletions
diff --git a/Changelog.md b/Changelog.md
index ed3cdfea..c9e76ee5 100644
--- a/Changelog.md
+++ b/Changelog.md
@@ -4,6 +4,8 @@ Features:
* Code Generator: Always use all available gas for calls as experimental 0.5.0 feature
(previously, some amount was retained in order to work in pre-tangerine whistle
EVM versions)
+ * Code Generator: Do not accept data with less than four bytes (truncated function
+ signature) for regular function calls - fallback function is invoked instead.
* Parser: Better error message for unexpected trailing comma in parameter lists.
* Standard JSON: Support the ``outputSelection`` field for selective compilation of supplied sources.
* Syntax Checker: Unary ``+`` is now a syntax error as experimental 0.5.0 feature.
diff --git a/libsolidity/codegen/ContractCompiler.cpp b/libsolidity/codegen/ContractCompiler.cpp
index 429db532..74565ae4 100644
--- a/libsolidity/codegen/ContractCompiler.cpp
+++ b/libsolidity/codegen/ContractCompiler.cpp
@@ -251,13 +251,10 @@ void ContractCompiler::appendFunctionSelector(ContractDefinition const& _contrac
FunctionDefinition const* fallback = _contract.fallbackFunction();
eth::AssemblyItem notFound = m_context.newTag();
- // shortcut messages without data if we have many functions in order to be able to receive
- // ether with constant gas
- if (interfaceFunctions.size() > 5 || fallback)
- {
- m_context << Instruction::CALLDATASIZE << Instruction::ISZERO;
- m_context.appendConditionalJumpTo(notFound);
- }
+ // directly jump to fallback if the data is too short to contain a function selector
+ // also guards against short data
+ m_context << u256(4) << Instruction::CALLDATASIZE << Instruction::LT;
+ m_context.appendConditionalJumpTo(notFound);
// retrieve the function signature hash from the calldata
if (!interfaceFunctions.empty())
diff --git a/test/libsolidity/SolidityEndToEndTest.cpp b/test/libsolidity/SolidityEndToEndTest.cpp
index 648c13cb..9a837113 100644
--- a/test/libsolidity/SolidityEndToEndTest.cpp
+++ b/test/libsolidity/SolidityEndToEndTest.cpp
@@ -2899,6 +2899,25 @@ BOOST_AUTO_TEST_CASE(default_fallback_throws)
ABI_CHECK(callContractFunction("f()"), encodeArgs(0));
}
+BOOST_AUTO_TEST_CASE(short_data_calls_fallback)
+{
+ char const* sourceCode = R"(
+ contract A {
+ uint public x;
+ // Signature is d88e0b00
+ function fow() { x = 3; }
+ function () { x = 2; }
+ }
+ )";
+ compileAndRun(sourceCode);
+ // should call fallback
+ sendMessage(asBytes("\xd8\x8e\x0b"), false, 0);
+ ABI_CHECK(callContractFunction("x()"), encodeArgs(2));
+ // should call function
+ sendMessage(asBytes(string("\xd8\x8e\x0b") + string(1, 0)), false, 0);
+ ABI_CHECK(callContractFunction("x()"), encodeArgs(3));
+}
+
BOOST_AUTO_TEST_CASE(event)
{
char const* sourceCode = R"(