diff options
Diffstat (limited to 'libsolidity/codegen/CompilerUtils.cpp')
-rw-r--r-- | libsolidity/codegen/CompilerUtils.cpp | 34 |
1 files changed, 24 insertions, 10 deletions
diff --git a/libsolidity/codegen/CompilerUtils.cpp b/libsolidity/codegen/CompilerUtils.cpp index 79aef7b0..4af7d905 100644 --- a/libsolidity/codegen/CompilerUtils.cpp +++ b/libsolidity/codegen/CompilerUtils.cpp @@ -78,6 +78,20 @@ void CompilerUtils::toSizeAfterFreeMemoryPointer() m_context << Instruction::SWAP1; } +void CompilerUtils::revertWithStringData(Type const& _argumentType) +{ + solAssert(_argumentType.isImplicitlyConvertibleTo(*Type::fromElementaryTypeName("string memory")), ""); + fetchFreeMemoryPointer(); + m_context << (u256(FixedHash<4>::Arith(FixedHash<4>(dev::keccak256("Error(string)")))) << (256 - 32)); + m_context << Instruction::DUP2 << Instruction::MSTORE; + m_context << u256(4) << Instruction::ADD; + // Stack: <string data> <mem pos of encoding start> + abiEncode({_argumentType.shared_from_this()}, {make_shared<ArrayType>(DataLocation::Memory, true)}); + toSizeAfterFreeMemoryPointer(); + m_context << Instruction::REVERT; + m_context.adjustStackOffset(_argumentType.sizeOnStack()); +} + unsigned CompilerUtils::loadFromMemory( unsigned _offset, Type const& _type, @@ -670,19 +684,17 @@ void CompilerUtils::convertType( // clear for conversion to longer bytes solAssert(targetTypeCategory == Type::Category::FixedBytes, "Invalid type conversion requested."); FixedBytesType const& targetType = dynamic_cast<FixedBytesType const&>(_targetType); - if (targetType.numBytes() > typeOnStack.numBytes() || _cleanupNeeded) + if (typeOnStack.numBytes() == 0 || targetType.numBytes() == 0) + m_context << Instruction::POP << u256(0); + else if (targetType.numBytes() > typeOnStack.numBytes() || _cleanupNeeded) { - if (typeOnStack.numBytes() == 0) - m_context << Instruction::POP << u256(0); - else - { - m_context << ((u256(1) << (256 - typeOnStack.numBytes() * 8)) - 1); - m_context << Instruction::NOT << Instruction::AND; - } + int bytes = min(typeOnStack.numBytes(), targetType.numBytes()); + m_context << ((u256(1) << (256 - bytes * 8)) - 1); + m_context << Instruction::NOT << Instruction::AND; } } - } break; + } case Type::Category::Enum: solAssert(_targetType == _typeOnStack || targetTypeCategory == Type::Category::Integer, ""); if (enumOverflowCheckPending) @@ -691,6 +703,7 @@ void CompilerUtils::convertType( solAssert(enumType.numberOfMembers() > 0, "empty enum should have caused a parser error."); m_context << u256(enumType.numberOfMembers() - 1) << Instruction::DUP2 << Instruction::GT; if (_asPartOfArgumentDecoding) + // TODO: error message? m_context.appendConditionalRevert(); else m_context.appendConditionalInvalid(); @@ -783,8 +796,9 @@ void CompilerUtils::convertType( bytesConstRef data(value); if (targetTypeCategory == Type::Category::FixedBytes) { + int const numBytes = dynamic_cast<FixedBytesType const&>(_targetType).numBytes(); solAssert(data.size() <= 32, ""); - m_context << h256::Arith(h256(data, h256::AlignLeft)); + m_context << (h256::Arith(h256(data, h256::AlignLeft)) & (~(u256(-1) >> (8 * numBytes)))); } else if (targetTypeCategory == Type::Category::Array) { |