aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorchriseth <c@ethdev.com>2016-07-28 23:19:17 +0800
committerchriseth <c@ethdev.com>2016-07-28 23:24:18 +0800
commit58cc6cbb379015d57b8f6dec3b4a5c207ccb6b0b (patch)
tree5f838b1813be0088e459c205af14cd04392a138b
parentea4fd3c6e25517180a773a6e4b51de0505e781ec (diff)
downloaddexon-solidity-58cc6cbb379015d57b8f6dec3b4a5c207ccb6b0b.tar.gz
dexon-solidity-58cc6cbb379015d57b8f6dec3b4a5c207ccb6b0b.tar.zst
dexon-solidity-58cc6cbb379015d57b8f6dec3b4a5c207ccb6b0b.zip
Bugfix: Allocate empty array.
-rw-r--r--libsolidity/codegen/CompilerUtils.h1
-rw-r--r--libsolidity/codegen/ExpressionCompiler.cpp9
-rw-r--r--test/libsolidity/SolidityEndToEndTest.cpp14
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()
}