diff --git a/libsolidity/ExpressionCompiler.cpp b/libsolidity/ExpressionCompiler.cpp index 9d282c1cb..2c3b4078e 100644 --- a/libsolidity/ExpressionCompiler.cpp +++ b/libsolidity/ExpressionCompiler.cpp @@ -629,17 +629,25 @@ void ExpressionCompiler::appendTypeConversion(Type const& _typeOnStack, Type con Type::Category stackTypeCategory = _typeOnStack.getCategory(); Type::Category targetTypeCategory = _targetType.getCategory(); - if (stackTypeCategory == Type::Category::STRING && targetTypeCategory == Type::Category::INTEGER) + if (stackTypeCategory == Type::Category::STRING) { - // conversion from string to hash. no need to clean the high bit - // only to shift right because of opposite alignment - IntegerType const& targetIntegerType = dynamic_cast(_targetType); - StaticStringType const& sourceStringType = dynamic_cast(_typeOnStack); - if (targetIntegerType.isHash()) + if (targetTypeCategory == Type::Category::INTEGER) { - solAssert(targetIntegerType.getNumBits() == sourceStringType.getNumBytes() * 8, "The size should be the same."); - m_context << u256(std::pow(2, 256 - sourceStringType.getNumBytes() * 8)) << - eth::Instruction::SWAP1 << eth::Instruction::DIV; + // conversion from string to hash. no need to clean the high bit + // only to shift right because of opposite alignment + IntegerType const& targetIntegerType = dynamic_cast(_targetType); + StaticStringType const& sourceStringType = dynamic_cast(_typeOnStack); + if (targetIntegerType.isHash()) + { + solAssert(targetIntegerType.getNumBits() == sourceStringType.getNumBytes() * 8, "The size should be the same."); + m_context << (u256(1) << 256 - sourceStringType.getNumBytes() * 8) << + eth::Instruction::SWAP1 << eth::Instruction::DIV; + } + } + else { + solAssert(targetTypeCategory == Type::Category::STRING, "Invalid type conversion requested."); + // nothing to do, strings are high-order-bit-aligned + //@todo clear lower-order bytes if we allow explicit conversion to shorter strings } } else if (targetTypeCategory == Type::Category::STRING && stackTypeCategory == Type::Category::INTEGER) @@ -651,7 +659,7 @@ void ExpressionCompiler::appendTypeConversion(Type const& _typeOnStack, Type con if (sourceIntegerType.isHash()) { solAssert(sourceIntegerType.getNumBits() == targetStringType.getNumBytes() * 8, "The size should be the same."); - m_context << u256(std::pow(2, 256 - sourceIntegerType.getNumBits())) << eth::Instruction::MUL; + m_context << (u256(1) << 256 - sourceIntegerType.getNumBits()) << eth::Instruction::MUL; } } else if (stackTypeCategory == Type::Category::INTEGER || stackTypeCategory == Type::Category::CONTRACT || @@ -681,12 +689,6 @@ void ExpressionCompiler::appendTypeConversion(Type const& _typeOnStack, Type con appendHighBitsCleanup(targetType); } } - else if (stackTypeCategory == Type::Category::STRING) - { - solAssert(targetTypeCategory == Type::Category::STRING, "Invalid type conversion requested."); - // nothing to do, strings are high-order-bit-aligned - //@todo clear lower-order bytes if we allow explicit conversion to shorter strings - } else if (_typeOnStack != _targetType) // All other types should not be convertible to non-equal types. BOOST_THROW_EXCEPTION(InternalCompilerError() << errinfo_comment("Invalid type conversion requested.")); diff --git a/test/SolidityEndToEndTest.cpp b/test/SolidityEndToEndTest.cpp index b0b450738..1d4839635 100644 --- a/test/SolidityEndToEndTest.cpp +++ b/test/SolidityEndToEndTest.cpp @@ -949,9 +949,6 @@ BOOST_AUTO_TEST_CASE(convert_string_to_string) } })"; compileAndRun(sourceCode); - string s = "abc"; - auto res = callContractFunction("pipeTrough(string3)", "abc"); - auto goldenRes = encodeArgs(s); BOOST_CHECK(callContractFunction("pipeTrough(string3)", "abc") == encodeArgs("abc")); } @@ -977,8 +974,8 @@ BOOST_AUTO_TEST_CASE(convert_hash_to_string_different_size) } })"; compileAndRun(sourceCode); - BOOST_CHECK(callContractFunction("hashToString(hash160)", u160("0x00000000000000616263")) == - encodeArgs(u256("0x0000000000000000000000000000000000616263000000000000000000000000"))); + BOOST_CHECK(callContractFunction("hashToString(hash160)", u160("0x6161626361626361626361616263616263616263")) == + encodeArgs(string("aabcabcabcaabcabcabc"))); } BOOST_AUTO_TEST_CASE(convert_string_to_hash_same_size) @@ -1003,8 +1000,22 @@ BOOST_AUTO_TEST_CASE(convert_string_to_hash_different_size) } })"; compileAndRun(sourceCode); - BOOST_CHECK(callContractFunction("stringToHash(string20)", u256("0x0000000000000000000000000000000000616263000000000000000000000000")) == - encodeArgs(u160("0x00000000000000616263"))); + BOOST_CHECK(callContractFunction("stringToHash(string20)", string("aabcabcabcaabcabcabc")) == + encodeArgs(u160("0x6161626361626361626361616263616263616263"))); +} + + +BOOST_AUTO_TEST_CASE(convert_string_to_hash_different_min_size) +{ + char const* sourceCode = R"( + contract Test { + function stringToHash(string1 s) returns (hash8 h) { + return hash8(s); + } + })"; + compileAndRun(sourceCode); + BOOST_CHECK(callContractFunction("stringToHash(string1)", string("a")) == + encodeArgs(u128("0x00000000000000000000000000000061"))); } BOOST_AUTO_TEST_CASE(send_ether)