diff options
author | chriseth <c@ethdev.com> | 2016-07-28 23:19:17 +0800 |
---|---|---|
committer | chriseth <c@ethdev.com> | 2016-07-28 23:24:18 +0800 |
commit | 58cc6cbb379015d57b8f6dec3b4a5c207ccb6b0b (patch) | |
tree | 5f838b1813be0088e459c205af14cd04392a138b | |
parent | ea4fd3c6e25517180a773a6e4b51de0505e781ec (diff) | |
download | dexon-solidity-58cc6cbb379015d57b8f6dec3b4a5c207ccb6b0b.tar.gz dexon-solidity-58cc6cbb379015d57b8f6dec3b4a5c207ccb6b0b.tar.zst dexon-solidity-58cc6cbb379015d57b8f6dec3b4a5c207ccb6b0b.zip |
Bugfix: Allocate empty array.
-rw-r--r-- | libsolidity/codegen/CompilerUtils.h | 1 | ||||
-rw-r--r-- | libsolidity/codegen/ExpressionCompiler.cpp | 9 | ||||
-rw-r--r-- | test/libsolidity/SolidityEndToEndTest.cpp | 14 |
3 files changed, 21 insertions, 3 deletions
diff --git a/libsolidity/codegen/CompilerUtils.h b/libsolidity/codegen/CompilerUtils.h index 55254013..da74dc90 100644 --- a/libsolidity/codegen/CompilerUtils.h +++ b/libsolidity/codegen/CompilerUtils.h @@ -104,6 +104,7 @@ public: ); /// Zero-initialises (the data part of) an already allocated memory array. + /// Length has to be nonzero! /// Stack pre: <length> <memptr> /// Stack post: <updated_memptr> void zeroInitialiseMemoryArray(ArrayType const& _type); diff --git a/libsolidity/codegen/ExpressionCompiler.cpp b/libsolidity/codegen/ExpressionCompiler.cpp index b973a117..80009a90 100644 --- a/libsolidity/codegen/ExpressionCompiler.cpp +++ b/libsolidity/codegen/ExpressionCompiler.cpp @@ -792,15 +792,18 @@ bool ExpressionCompiler::visit(FunctionCall const& _functionCall) utils().storeFreeMemoryPointer(); // Stack: memptr requested_length + // Check if length is zero + m_context << Instruction::DUP1 << Instruction::ISZERO; + auto skipInit = m_context.appendConditionalJump(); + // We only have to initialise if the base type is a not a value type. if (dynamic_cast<ReferenceType const*>(arrayType.baseType().get())) { m_context << Instruction::DUP2 << u256(32) << Instruction::ADD; utils().zeroInitialiseMemoryArray(arrayType); - m_context << Instruction::POP; } - else - m_context << Instruction::POP; + m_context << skipInit; + m_context << Instruction::POP; break; } default: diff --git a/test/libsolidity/SolidityEndToEndTest.cpp b/test/libsolidity/SolidityEndToEndTest.cpp index 8dcc878e..4b634649 100644 --- a/test/libsolidity/SolidityEndToEndTest.cpp +++ b/test/libsolidity/SolidityEndToEndTest.cpp @@ -6837,6 +6837,20 @@ BOOST_AUTO_TEST_CASE(skip_dynamic_types_for_structs) BOOST_CHECK(callContractFunction("g()") == encodeArgs(u256(2), u256(6))); } +BOOST_AUTO_TEST_CASE(create_dynamic_array_with_zero_length) +{ + char const* sourceCode = R"( + contract C { + function f() returns (uint) { + var a = new uint[][](0); + return 7; + } + } + )"; + compileAndRun(sourceCode, 0, "C"); + BOOST_CHECK(callContractFunction("f()") == encodeArgs(u256(7))); +} + BOOST_AUTO_TEST_SUITE_END() } |