Merge pull request #5316 from lazaridiscom/4891-memory-store-asserts

refine memory-store assertions, closes #4891
This commit is contained in:
chriseth 2018-10-28 20:50:41 +01:00 committed by GitHub
commit 4d82831b06
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23

View File

@ -142,9 +142,13 @@ void CompilerUtils::storeInMemory(unsigned _offset)
void CompilerUtils::storeInMemoryDynamic(Type const& _type, bool _padToWordBoundaries) void CompilerUtils::storeInMemoryDynamic(Type const& _type, bool _padToWordBoundaries)
{ {
// process special types (Reference, StringLiteral, Function)
if (auto ref = dynamic_cast<ReferenceType const*>(&_type)) if (auto ref = dynamic_cast<ReferenceType const*>(&_type))
{ {
solUnimplementedAssert(ref->location() == DataLocation::Memory, "Only in-memory reference type can be stored."); solUnimplementedAssert(
ref->location() == DataLocation::Memory,
"Only in-memory reference type can be stored."
);
storeInMemoryDynamic(IntegerType(256), _padToWordBoundaries); storeInMemoryDynamic(IntegerType(256), _padToWordBoundaries);
} }
else if (auto str = dynamic_cast<StringLiteralType const*>(&_type)) else if (auto str = dynamic_cast<StringLiteralType const*>(&_type))
@ -166,18 +170,18 @@ void CompilerUtils::storeInMemoryDynamic(Type const& _type, bool _padToWordBound
m_context << Instruction::DUP2 << Instruction::MSTORE; m_context << Instruction::DUP2 << Instruction::MSTORE;
m_context << u256(_padToWordBoundaries ? 32 : 24) << Instruction::ADD; m_context << u256(_padToWordBoundaries ? 32 : 24) << Instruction::ADD;
} }
else else if (_type.isValueType())
{ {
unsigned numBytes = prepareMemoryStore(_type, _padToWordBoundaries); unsigned numBytes = prepareMemoryStore(_type, _padToWordBoundaries);
if (numBytes > 0) m_context << Instruction::DUP2 << Instruction::MSTORE;
{ m_context << u256(numBytes) << Instruction::ADD;
solUnimplementedAssert( }
_type.sizeOnStack() == 1, else // Should never happen
"Memory store of types with stack size != 1 not implemented." {
); solAssert(
m_context << Instruction::DUP2 << Instruction::MSTORE; false,
m_context << u256(numBytes) << Instruction::ADD; "Memory store of type " + _type.toString(true) + " not allowed."
} );
} }
} }
@ -1266,18 +1270,30 @@ void CompilerUtils::rightShiftNumberOnStack(unsigned _bits)
unsigned CompilerUtils::prepareMemoryStore(Type const& _type, bool _padToWords) unsigned CompilerUtils::prepareMemoryStore(Type const& _type, bool _padToWords)
{ {
solAssert(
_type.sizeOnStack() == 1,
"Memory store of types with stack size != 1 not allowed (Type: " + _type.toString(true) + ")."
);
unsigned numBytes = _type.calldataEncodedSize(_padToWords); unsigned numBytes = _type.calldataEncodedSize(_padToWords);
solAssert(
numBytes > 0,
"Memory store of 0 bytes requested (Type: " + _type.toString(true) + ")."
);
solAssert(
numBytes <= 32,
"Memory store of more than 32 bytes requested (Type: " + _type.toString(true) + ")."
);
bool leftAligned = _type.category() == Type::Category::FixedBytes; bool leftAligned = _type.category() == Type::Category::FixedBytes;
if (numBytes == 0)
m_context << Instruction::POP; convertType(_type, _type, true);
else if (numBytes != 32 && !leftAligned && !_padToWords)
{ // shift the value accordingly before storing
solAssert(numBytes <= 32, "Memory store of more than 32 bytes requested."); leftShiftNumberOnStack((32 - numBytes) * 8);
convertType(_type, _type, true);
if (numBytes != 32 && !leftAligned && !_padToWords)
// shift the value accordingly before storing
leftShiftNumberOnStack((32 - numBytes) * 8);
}
return numBytes; return numBytes;
} }