aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorchriseth <chris@ethereum.org>2017-10-11 18:28:21 +0800
committerchriseth <chris@ethereum.org>2017-10-17 04:29:31 +0800
commit6001bd1406e7adbb6607485afb775bbb5b6c2ac3 (patch)
tree7f5151acaf7e12f9b12818cfd20a95bf24f53849
parent7989fc4c356929de47e2d696ef5478c398941508 (diff)
downloaddexon-solidity-6001bd1406e7adbb6607485afb775bbb5b6c2ac3.tar.gz
dexon-solidity-6001bd1406e7adbb6607485afb775bbb5b6c2ac3.tar.zst
dexon-solidity-6001bd1406e7adbb6607485afb775bbb5b6c2ac3.zip
Allocate one byte per memory byte array element instead of 32.
-rw-r--r--Changelog.md1
-rw-r--r--libsolidity/codegen/ExpressionCompiler.cpp11
-rw-r--r--test/libsolidity/SolidityEndToEndTest.cpp24
3 files changed, 34 insertions, 2 deletions
diff --git a/Changelog.md b/Changelog.md
index c8ea21f5..ed3cdfea 100644
--- a/Changelog.md
+++ b/Changelog.md
@@ -13,6 +13,7 @@ Features:
* Type Checker: Require ``storage`` or ``memory`` keyword for local variables as experimental 0.5.0 feature.
Bugfixes:
+ * Code Generator: Allocate one byte per memory byte array element instead of 32.
* Optimizer: Remove unused stack computation results.
* Parser: Fix source location of VariableDeclarationStatement.
* Type Checker: Properly check array length and don't rely on an assertion in code generation.
diff --git a/libsolidity/codegen/ExpressionCompiler.cpp b/libsolidity/codegen/ExpressionCompiler.cpp
index fe37baac..bb8c4a94 100644
--- a/libsolidity/codegen/ExpressionCompiler.cpp
+++ b/libsolidity/codegen/ExpressionCompiler.cpp
@@ -858,8 +858,15 @@ bool ExpressionCompiler::visit(FunctionCall const& _functionCall)
m_context << Instruction::DUP1 << Instruction::DUP3 << Instruction::MSTORE;
// Stack: memptr requested_length
// update free memory pointer
- m_context << Instruction::DUP1 << arrayType.baseType()->memoryHeadSize();
- m_context << Instruction::MUL << u256(32) << Instruction::ADD;
+ m_context << Instruction::DUP1;
+ // Stack: memptr requested_length requested_length
+ if (arrayType.isByteArray())
+ // Round up to multiple of 32
+ m_context << u256(31) << Instruction::ADD << u256(31) << Instruction::NOT << Instruction::AND;
+ else
+ m_context << arrayType.baseType()->memoryHeadSize() << Instruction::MUL;
+ // stacK: memptr requested_length data_size
+ m_context << u256(32) << Instruction::ADD;
m_context << Instruction::DUP3 << Instruction::ADD;
utils().storeFreeMemoryPointer();
// Stack: memptr requested_length
diff --git a/test/libsolidity/SolidityEndToEndTest.cpp b/test/libsolidity/SolidityEndToEndTest.cpp
index ac77a7e1..648c13cb 100644
--- a/test/libsolidity/SolidityEndToEndTest.cpp
+++ b/test/libsolidity/SolidityEndToEndTest.cpp
@@ -7309,6 +7309,30 @@ BOOST_AUTO_TEST_CASE(create_memory_array)
ABI_CHECK(callContractFunction("f()"), encodeArgs(string("A"), u256(8), u256(4), string("B")));
}
+BOOST_AUTO_TEST_CASE(create_memory_array_allocation_size)
+{
+ // Check allocation size of byte array. Should be 32 plus length rounded up to next
+ // multiple of 32
+ char const* sourceCode = R"(
+ contract C {
+ function f() pure returns (uint d1, uint d2, uint d3) {
+ bytes memory b1 = new bytes(31);
+ bytes memory b2 = new bytes(32);
+ bytes memory b3 = new bytes(256);
+ bytes memory b4 = new bytes(31);
+ assembly {
+ d1 := sub(b2, b1)
+ d2 := sub(b3, b2)
+ d3 := sub(b4, b3)
+ }
+ }
+ }
+ )";
+ compileAndRun(sourceCode);
+ ABI_CHECK(callContractFunction("f()"), encodeArgs(0x40, 0x40, 0x20 + 256));
+}
+
+
BOOST_AUTO_TEST_CASE(memory_arrays_of_various_sizes)
{
// Computes binomial coefficients the chinese way