mirror of
https://github.com/ethereum/solidity
synced 2023-10-03 13:03:40 +00:00
Merge pull request #3067 from ethereum/correct_byte_array_allocation
Allocate one byte per memory byte array element instead of 32.
This commit is contained in:
commit
8fbfd62d15
@ -13,6 +13,7 @@ Features:
|
|||||||
* Type Checker: Require ``storage`` or ``memory`` keyword for local variables as experimental 0.5.0 feature.
|
* Type Checker: Require ``storage`` or ``memory`` keyword for local variables as experimental 0.5.0 feature.
|
||||||
|
|
||||||
Bugfixes:
|
Bugfixes:
|
||||||
|
* Code Generator: Allocate one byte per memory byte array element instead of 32.
|
||||||
* Optimizer: Remove unused stack computation results.
|
* Optimizer: Remove unused stack computation results.
|
||||||
* Parser: Fix source location of VariableDeclarationStatement.
|
* Parser: Fix source location of VariableDeclarationStatement.
|
||||||
* Type Checker: Properly check array length and don't rely on an assertion in code generation.
|
* Type Checker: Properly check array length and don't rely on an assertion in code generation.
|
||||||
|
@ -858,8 +858,15 @@ bool ExpressionCompiler::visit(FunctionCall const& _functionCall)
|
|||||||
m_context << Instruction::DUP1 << Instruction::DUP3 << Instruction::MSTORE;
|
m_context << Instruction::DUP1 << Instruction::DUP3 << Instruction::MSTORE;
|
||||||
// Stack: memptr requested_length
|
// Stack: memptr requested_length
|
||||||
// update free memory pointer
|
// update free memory pointer
|
||||||
m_context << Instruction::DUP1 << arrayType.baseType()->memoryHeadSize();
|
m_context << Instruction::DUP1;
|
||||||
m_context << Instruction::MUL << u256(32) << Instruction::ADD;
|
// 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;
|
m_context << Instruction::DUP3 << Instruction::ADD;
|
||||||
utils().storeFreeMemoryPointer();
|
utils().storeFreeMemoryPointer();
|
||||||
// Stack: memptr requested_length
|
// Stack: memptr requested_length
|
||||||
|
@ -7309,6 +7309,30 @@ BOOST_AUTO_TEST_CASE(create_memory_array)
|
|||||||
ABI_CHECK(callContractFunction("f()"), encodeArgs(string("A"), u256(8), u256(4), string("B")));
|
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)
|
BOOST_AUTO_TEST_CASE(memory_arrays_of_various_sizes)
|
||||||
{
|
{
|
||||||
// Computes binomial coefficients the chinese way
|
// Computes binomial coefficients the chinese way
|
||||||
|
Loading…
Reference in New Issue
Block a user