From 0135cae2229e2097f139915e5ff7169c5e6be39a Mon Sep 17 00:00:00 2001 From: hrkrshnn Date: Fri, 12 Feb 2021 17:40:00 +0100 Subject: [PATCH 1/2] Fix IR bug: constructor parameter that needs multiple stack slots When an argument had multiple stack slots, like `function() external`, there wasn't enough variables assigned for the constructor. This lead to some mismatch between return values and arguments between some functions. --- libsolidity/codegen/YulUtilFunctions.cpp | 2 +- libsolidity/codegen/ir/IRGenerator.cpp | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/libsolidity/codegen/YulUtilFunctions.cpp b/libsolidity/codegen/YulUtilFunctions.cpp index 8ad3fe571..56800d8fe 100644 --- a/libsolidity/codegen/YulUtilFunctions.cpp +++ b/libsolidity/codegen/YulUtilFunctions.cpp @@ -4255,7 +4255,7 @@ string YulUtilFunctions::copyConstructorArgumentsToMemoryFunction( toString(_contract.id()); return m_functionCollector.createFunction(functionName, [&]() { - string returnParams = suffixedVariableNameList("ret_param_",0, _contract.constructor()->parameters().size()); + string returnParams = suffixedVariableNameList("ret_param_",0, CompilerUtils::sizeOnStack(_contract.constructor()->parameters())); ABIFunctions abiFunctions(m_evmVersion, m_revertStrings, m_functionCollector); return util::Whiskers(R"( diff --git a/libsolidity/codegen/ir/IRGenerator.cpp b/libsolidity/codegen/ir/IRGenerator.cpp index 22670500c..bec31200c 100644 --- a/libsolidity/codegen/ir/IRGenerator.cpp +++ b/libsolidity/codegen/ir/IRGenerator.cpp @@ -129,7 +129,7 @@ string IRGenerator::generate( vector constructorParams; if (constructor && !constructor->parameters().empty()) { - for (size_t i = 0; i < constructor->parameters().size(); ++i) + for (size_t i = 0; i < CompilerUtils::sizeOnStack(constructor->parameters()); ++i) constructorParams.emplace_back(m_context.newYulVariable()); t( "copyConstructorArguments", From e24a23edcd0676436780c5be29431e89f212955a Mon Sep 17 00:00:00 2001 From: hrkrshnn Date: Fri, 12 Feb 2021 20:01:01 +0100 Subject: [PATCH 2/2] Semantic test where constructor has a function as parameter --- .../constructor_function_argument.sol | 9 ++++++++ .../constructor_function_complex.sol | 21 +++++++++++++++++++ 2 files changed, 30 insertions(+) create mode 100644 test/libsolidity/semanticTests/constructor/constructor_function_argument.sol create mode 100644 test/libsolidity/semanticTests/constructor/constructor_function_complex.sol diff --git a/test/libsolidity/semanticTests/constructor/constructor_function_argument.sol b/test/libsolidity/semanticTests/constructor/constructor_function_argument.sol new file mode 100644 index 000000000..b52f10de0 --- /dev/null +++ b/test/libsolidity/semanticTests/constructor/constructor_function_argument.sol @@ -0,0 +1,9 @@ +// The IR of this test used to throw +contract D { + constructor(function() external returns (uint)) { + } +} +// ==== +// compileViaYul: also +// ---- +// constructor(): 0xfdd67305928fcac8d213d1e47bfa6165cd0b87b946644cd0000000000000000 -> diff --git a/test/libsolidity/semanticTests/constructor/constructor_function_complex.sol b/test/libsolidity/semanticTests/constructor/constructor_function_complex.sol new file mode 100644 index 000000000..1fbb16c2a --- /dev/null +++ b/test/libsolidity/semanticTests/constructor/constructor_function_complex.sol @@ -0,0 +1,21 @@ +contract D { + uint public x; + constructor(function() external pure returns (uint) g) { + x = g(); + } +} + +contract C { + function f() public returns (uint r) { + D d = new D(this.sixteen); + r = d.x(); + } + + function sixteen() public pure returns (uint) { + return 16; + } +} +// ==== +// compileViaYul: also +// ---- +// f() -> 16