Merge pull request #244 from chriseth/fix_stringAlloc

Fix for memory allocation bug.
This commit is contained in:
chriseth 2015-11-24 16:18:41 +01:00
commit aa8e9e66ed
7 changed files with 39 additions and 14 deletions

View File

@ -781,7 +781,7 @@ bool ArrayType::operator==(Type const& _other) const
unsigned ArrayType::calldataEncodedSize(bool _padded) const
{
if (isDynamicallySized())
return 0;
return 32;
bigint size = bigint(length()) * (isByteArray() ? 1 : baseType()->calldataEncodedSize(_padded));
size = ((size + 31) / 32) * 32;
solAssert(size <= numeric_limits<unsigned>::max(), "Array size does not fit unsigned.");
@ -1698,7 +1698,7 @@ FunctionTypePointer FunctionType::asMemberFunction(bool _inLibrary) const
TypePointers returnParameterTypes;
vector<string> returnParameterNames;
for (size_t i = 0; i < m_returnParameterTypes.size(); ++i)
if (m_returnParameterTypes[i]->calldataEncodedSize() > 0)
if (!m_returnParameterTypes[i]->isDynamicallySized())
{
returnParameterTypes.push_back(m_returnParameterTypes[i]);
returnParameterNames.push_back(m_returnParameterNames[i]);

View File

@ -175,8 +175,9 @@ public:
virtual bool operator==(Type const& _other) const { return category() == _other.category(); }
virtual bool operator!=(Type const& _other) const { return !this->operator ==(_other); }
/// @returns number of bytes used by this type when encoded for CALL, or 0 if the encoding
/// is not a simple big-endian encoding or the type cannot be stored in calldata.
/// @returns number of bytes used by this type when encoded for CALL. If it is a dynamic type,
/// returns the size of the pointer (usually 32). Returns 0 if the type cannot be encoded
/// in calldata.
/// If @a _padded then it is assumed that each element is padded to a multiple of 32 bytes.
virtual unsigned calldataEncodedSize(bool _padded) const { (void)_padded; return 0; }
/// @returns the size of this data type in bytes when stored in memory. For memory-reference

View File

@ -271,7 +271,7 @@ void ArrayUtils::copyArrayToStorage(ArrayType const& _targetType, ArrayType cons
void ArrayUtils::copyArrayToMemory(ArrayType const& _sourceType, bool _padToWordBoundaries) const
{
solAssert(
_sourceType.baseType()->calldataEncodedSize() > 0,
!_sourceType.baseType()->isDynamicallySized(),
"Nested dynamic arrays not implemented here."
);
CompilerUtils utils(m_context);

View File

@ -92,13 +92,6 @@ private:
void registerStateVariables(ContractDefinition const& _contract);
void initializeStateVariables(ContractDefinition const& _contract);
/// Initialises all memory arrays in the local variables to point to an empty location.
void initialiseMemoryArrays(std::vector<VariableDeclaration const*> _variables);
/// Pushes the initialised value of the given type to the stack. If the type is a memory
/// reference type, allocates memory and pushes the memory pointer.
/// Not to be used for storage references.
void initialiseInMemory(Type const& _type);
virtual bool visit(VariableDeclaration const& _variableDeclaration) override;
virtual bool visit(FunctionDefinition const& _function) override;
virtual bool visit(IfStatement const& _ifStatement) override;

View File

@ -613,7 +613,7 @@ void CompilerUtils::convertType(Type const& _typeOnStack, Type const& _targetTyp
}
}
void CompilerUtils::pushZeroValue(const Type& _type)
void CompilerUtils::pushZeroValue(Type const& _type)
{
auto const* referenceType = dynamic_cast<ReferenceType const*>(&_type);
if (!referenceType || referenceType->location() == DataLocation::Storage)

View File

@ -1226,7 +1226,7 @@ void ExpressionCompiler::appendExternalFunctionCall(
else
for (auto const& retType: _functionType.returnParameterTypes())
{
solAssert(retType->calldataEncodedSize() > 0, "Unable to return dynamic type from external call.");
solAssert(!retType->isDynamicallySized(), "Unable to return dynamic type from external call.");
retSize += retType->calldataEncodedSize();
}

View File

@ -5849,6 +5849,37 @@ BOOST_AUTO_TEST_CASE(addmod_mulmod)
compileAndRun(sourceCode);
BOOST_CHECK(callContractFunction("test()") == encodeArgs(u256(0)));
}
BOOST_AUTO_TEST_CASE(string_allocation_bug)
{
char const* sourceCode = R"(
contract Sample
{
struct s { uint16 x; uint16 y; string a; string b;}
s[2] public p;
function Sample() {
s memory m;
m.x = 0xbbbb;
m.y = 0xcccc;
m.a = "hello";
m.b = "world";
p[0] = m;
}
}
)";
compileAndRun(sourceCode);
BOOST_CHECK(callContractFunction("p(uint256)") == encodeArgs(
u256(0xbbbb),
u256(0xcccc),
u256(0x80),
u256(0xc0),
u256(5),
string("hello"),
u256(5),
string("world")
));
}
BOOST_AUTO_TEST_SUITE_END()
}