diff --git a/Changelog.md b/Changelog.md index 39c79ec22..d271f2f66 100644 --- a/Changelog.md +++ b/Changelog.md @@ -1,5 +1,8 @@ ### 0.4.26 (unreleased) +Important Bugfixes: + * Code Generator: Fix initialization routine of uninitialized internal function pointers in constructor context. + Bugfixes: * General: Split rule list such that JavaScript environments with small stacks can use the compiler. diff --git a/libsolidity/codegen/CompilerUtils.cpp b/libsolidity/codegen/CompilerUtils.cpp index d9f172639..6cb6fcff5 100644 --- a/libsolidity/codegen/CompilerUtils.cpp +++ b/libsolidity/codegen/CompilerUtils.cpp @@ -1060,6 +1060,14 @@ void CompilerUtils::pushZeroValue(Type const& _type) m_context << m_context.lowLevelFunctionTag("$invalidFunction", 0, 0, [](CompilerContext& _context) { _context.appendInvalid(); }); + if (CompilerContext* runCon = m_context.runtimeContext()) + { + leftShiftNumberOnStack(32); + m_context << runCon->lowLevelFunctionTag("$invalidFunction", 0, 0, [](CompilerContext& _context) { + _context.appendInvalid(); + }).toSubAssemblyTag(m_context.runtimeSub()); + m_context << Instruction::OR; + } return; } } diff --git a/test/libsolidity/semanticTests/uninitializedFunctionPointer/invalidInConstructor.sol b/test/libsolidity/semanticTests/uninitializedFunctionPointer/invalidInConstructor.sol new file mode 100644 index 000000000..26c02f3e3 --- /dev/null +++ b/test/libsolidity/semanticTests/uninitializedFunctionPointer/invalidInConstructor.sol @@ -0,0 +1,23 @@ +contract C { + + function() internal storedFn; + + bool flag; + + constructor() public { + if (!flag) { + flag = true; + function() internal invalid; + storedFn = invalid; + invalid(); + } + } + function f() public pure {} +} +contract Test { + function f() public { + new C(); + } +} +// ---- +// f() -> FAILURE diff --git a/test/libsolidity/semanticTests/uninitializedFunctionPointer/invalidStoredInConstructor.sol b/test/libsolidity/semanticTests/uninitializedFunctionPointer/invalidStoredInConstructor.sol new file mode 100644 index 000000000..710348a1a --- /dev/null +++ b/test/libsolidity/semanticTests/uninitializedFunctionPointer/invalidStoredInConstructor.sol @@ -0,0 +1,23 @@ +contract C { + + function() internal storedFn; + + bool flag; + + constructor() public { + if (!flag) { + flag = true; + function() internal invalid; + storedFn = invalid; + storedFn(); + } + } + function f() public pure {} +} +contract Test { + function f() public { + new C(); + } +} +// ---- +// f() -> FAILURE diff --git a/test/libsolidity/semanticTests/uninitializedFunctionPointer/storeInConstructor.sol b/test/libsolidity/semanticTests/uninitializedFunctionPointer/storeInConstructor.sol new file mode 100644 index 000000000..8a11832c8 --- /dev/null +++ b/test/libsolidity/semanticTests/uninitializedFunctionPointer/storeInConstructor.sol @@ -0,0 +1,19 @@ +contract InvalidTest { + + function() internal storedFn; + + bool flag; + + constructor() public { + function() internal invalid; + storedFn = invalid; + } + function f() public returns (uint) { + if (flag) return 2; + flag = true; + storedFn(); + } +} +// ---- +// f() -> FAILURE +// f() -> FAILURE