diff --git a/Changelog.md b/Changelog.md index 150d77d74..12b2e848d 100644 --- a/Changelog.md +++ b/Changelog.md @@ -20,6 +20,7 @@ Compiler Features: Bugfixes: + * Code Generator: Explicitly turn uninitialized internal function pointers into invalid functions when loaded from storage. * Code Generator: Fix assertion failure when assigning structs containing array of mapping. * SMTChecker: Fix bad cast in base constructor modifier. * SMTChecker: Fix internal error when visiting state variable inherited from base class. diff --git a/libsolidity/codegen/LValue.cpp b/libsolidity/codegen/LValue.cpp index 4413d5ee4..a6b8ae779 100644 --- a/libsolidity/codegen/LValue.cpp +++ b/libsolidity/codegen/LValue.cpp @@ -206,6 +206,12 @@ void StorageItem::retrieveValue(SourceLocation const&, bool _remove) const CompilerUtils(m_context).splitExternalFunctionType(false); cleaned = true; } + else if (fun->kind() == FunctionType::Kind::Internal) + { + m_context << Instruction::DUP1 << Instruction::ISZERO; + CompilerUtils(m_context).pushZeroValue(*fun); + m_context << Instruction::MUL << Instruction::OR; + } } if (!cleaned) { diff --git a/test/libsolidity/SolidityEndToEndTest.cpp b/test/libsolidity/SolidityEndToEndTest.cpp index dad33c5ad..a6b304734 100644 --- a/test/libsolidity/SolidityEndToEndTest.cpp +++ b/test/libsolidity/SolidityEndToEndTest.cpp @@ -15683,6 +15683,40 @@ BOOST_AUTO_TEST_CASE(event_wrong_abi_name) BOOST_CHECK_EQUAL(m_logs[0].topics[0], dev::keccak256(string("Deposit(address,bytes32,uint256)"))); } +BOOST_AUTO_TEST_CASE(uninitialized_internal_storage_function) +{ + char const* sourceCode = R"( + contract Test { + function() internal x; + function f() public returns (uint r) { + function() internal t = x; + assembly { r := t } + } + } + )"; + compileAndRun(sourceCode, 0, "Test"); + + bytes result = callContractFunction("f()"); + BOOST_CHECK(!result.empty()); + BOOST_CHECK(result != encodeArgs(0)); +} + +BOOST_AUTO_TEST_CASE(uninitialized_internal_storage_function_call) +{ + char const* sourceCode = R"( + contract Test { + function() internal x; + function f() public returns (uint r) { + x(); + return 2; + } + } + )"; + compileAndRun(sourceCode, 0, "Test"); + + ABI_CHECK(callContractFunction("f()"), bytes{}); +} + BOOST_AUTO_TEST_SUITE_END() }