Browse Source

Support empty strings.

cl-refactor
Christian 10 years ago
parent
commit
37a15d96ea
  1. 2
      libsolidity/AST.cpp
  2. 4
      libsolidity/Compiler.cpp
  3. 18
      libsolidity/CompilerUtils.cpp
  4. 1
      libsolidity/Token.h
  5. 8
      libsolidity/Types.cpp
  6. 14
      test/solidityEndToEndTest.cpp
  7. 8
      test/solidityNameAndTypeResolution.cpp

2
libsolidity/AST.cpp

@ -339,7 +339,7 @@ void Literal::checkTypeRequirements()
{ {
m_type = Type::forLiteral(*this); m_type = Type::forLiteral(*this);
if (!m_type) if (!m_type)
BOOST_THROW_EXCEPTION(createTypeError("Literal value too large or too small.")); BOOST_THROW_EXCEPTION(createTypeError("Literal value too large."));
} }
} }

4
libsolidity/Compiler.cpp

@ -135,7 +135,7 @@ unsigned Compiler::appendCalldataUnpacker(FunctionDefinition const& _function, b
for (ASTPointer<VariableDeclaration> const& var: _function.getParameters()) for (ASTPointer<VariableDeclaration> const& var: _function.getParameters())
{ {
unsigned const numBytes = var->getType()->getCalldataEncodedSize(); unsigned const numBytes = var->getType()->getCalldataEncodedSize();
if (numBytes == 0 || numBytes > 32) if (numBytes > 32)
BOOST_THROW_EXCEPTION(CompilerError() BOOST_THROW_EXCEPTION(CompilerError()
<< errinfo_sourceLocation(var->getLocation()) << errinfo_sourceLocation(var->getLocation())
<< errinfo_comment("Type " + var->getType()->toString() + " not yet supported.")); << errinfo_comment("Type " + var->getType()->toString() + " not yet supported."));
@ -156,7 +156,7 @@ void Compiler::appendReturnValuePacker(FunctionDefinition const& _function)
{ {
Type const& paramType = *parameters[i]->getType(); Type const& paramType = *parameters[i]->getType();
unsigned numBytes = paramType.getCalldataEncodedSize(); unsigned numBytes = paramType.getCalldataEncodedSize();
if (numBytes == 0 || numBytes > 32) if (numBytes > 32)
BOOST_THROW_EXCEPTION(CompilerError() BOOST_THROW_EXCEPTION(CompilerError()
<< errinfo_sourceLocation(parameters[i]->getLocation()) << errinfo_sourceLocation(parameters[i]->getLocation())
<< errinfo_comment("Type " + paramType.toString() + " not yet supported.")); << errinfo_comment("Type " + paramType.toString() + " not yet supported."));

18
libsolidity/CompilerUtils.cpp

@ -33,9 +33,14 @@ namespace solidity
void CompilerUtils::loadFromMemory(unsigned _offset, unsigned _bytes, bool _leftAligned, bool _fromCalldata) void CompilerUtils::loadFromMemory(unsigned _offset, unsigned _bytes, bool _leftAligned, bool _fromCalldata)
{ {
if (_bytes == 0)
{
m_context << u256(0);
return;
}
eth::Instruction load = _fromCalldata ? eth::Instruction::CALLDATALOAD : eth::Instruction::MLOAD; eth::Instruction load = _fromCalldata ? eth::Instruction::CALLDATALOAD : eth::Instruction::MLOAD;
if (asserts(0 < _bytes && _bytes <= 32)) if (asserts(_bytes <= 32))
BOOST_THROW_EXCEPTION(InternalCompilerError() << errinfo_comment("Memory load of 0 or more than 32 bytes requested.")); BOOST_THROW_EXCEPTION(InternalCompilerError() << errinfo_comment("Memory load of more than 32 bytes requested."));
if (_bytes == 32) if (_bytes == 32)
m_context << u256(_offset) << load; m_context << u256(_offset) << load;
else else
@ -53,8 +58,13 @@ void CompilerUtils::loadFromMemory(unsigned _offset, unsigned _bytes, bool _left
void CompilerUtils::storeInMemory(unsigned _offset, unsigned _bytes, bool _leftAligned) void CompilerUtils::storeInMemory(unsigned _offset, unsigned _bytes, bool _leftAligned)
{ {
if (asserts(0 < _bytes && _bytes <= 32)) if (_bytes == 0)
BOOST_THROW_EXCEPTION(InternalCompilerError() << errinfo_comment("Memory store of 0 or more than 32 bytes requested.")); {
m_context << eth::Instruction::POP;
return;
}
if (asserts(_bytes <= 32))
BOOST_THROW_EXCEPTION(InternalCompilerError() << errinfo_comment("Memory store of more than 32 bytes requested."));
if (_bytes != 32 && !_leftAligned) if (_bytes != 32 && !_leftAligned)
// shift the value accordingly before storing // shift the value accordingly before storing
m_context << (u256(1) << ((32 - _bytes) * 8)) << eth::Instruction::MUL; m_context << (u256(1) << ((32 - _bytes) * 8)) << eth::Instruction::MUL;

1
libsolidity/Token.h

@ -269,6 +269,7 @@ namespace solidity
K(ADDRESS, "address", 0) \ K(ADDRESS, "address", 0) \
K(BOOL, "bool", 0) \ K(BOOL, "bool", 0) \
K(STRING_TYPE, "string", 0) \ K(STRING_TYPE, "string", 0) \
K(STRING0, "string0", 0) \
K(STRING1, "string1", 0) \ K(STRING1, "string1", 0) \
K(STRING2, "string2", 0) \ K(STRING2, "string2", 0) \
K(STRING3, "string3", 0) \ K(STRING3, "string3", 0) \

8
libsolidity/Types.cpp

@ -53,8 +53,8 @@ shared_ptr<Type const> Type::fromElementaryTypeName(Token::Value _typeToken)
return make_shared<IntegerType const>(0, IntegerType::Modifier::ADDRESS); return make_shared<IntegerType const>(0, IntegerType::Modifier::ADDRESS);
else if (_typeToken == Token::BOOL) else if (_typeToken == Token::BOOL)
return make_shared<BoolType const>(); return make_shared<BoolType const>();
else if (Token::STRING1 <= _typeToken && _typeToken <= Token::STRING32) else if (Token::STRING0 <= _typeToken && _typeToken <= Token::STRING32)
return make_shared<StaticStringType const>(int(_typeToken) - int(Token::STRING1) + 1); return make_shared<StaticStringType const>(int(_typeToken) - int(Token::STRING0));
else else
BOOST_THROW_EXCEPTION(InternalCompilerError() << errinfo_comment("Unable to convert elementary typename " + BOOST_THROW_EXCEPTION(InternalCompilerError() << errinfo_comment("Unable to convert elementary typename " +
std::string(Token::toString(_typeToken)) + " to type.")); std::string(Token::toString(_typeToken)) + " to type."));
@ -199,14 +199,14 @@ const MemberList IntegerType::AddressMemberList =
shared_ptr<StaticStringType> StaticStringType::smallestTypeForLiteral(string const& _literal) shared_ptr<StaticStringType> StaticStringType::smallestTypeForLiteral(string const& _literal)
{ {
if (0 < _literal.length() && _literal.length() <= 32) if (_literal.length() <= 32)
return make_shared<StaticStringType>(_literal.length()); return make_shared<StaticStringType>(_literal.length());
return shared_ptr<StaticStringType>(); return shared_ptr<StaticStringType>();
} }
StaticStringType::StaticStringType(int _bytes): m_bytes(_bytes) StaticStringType::StaticStringType(int _bytes): m_bytes(_bytes)
{ {
if (asserts(m_bytes > 0 && m_bytes <= 32)) if (asserts(m_bytes >= 0 && m_bytes <= 32))
BOOST_THROW_EXCEPTION(InternalCompilerError() << errinfo_comment("Invalid byte number for static string type: " + BOOST_THROW_EXCEPTION(InternalCompilerError() << errinfo_comment("Invalid byte number for static string type: " +
dev::toString(m_bytes))); dev::toString(m_bytes)));
} }

14
test/solidityEndToEndTest.cpp

@ -510,6 +510,20 @@ BOOST_AUTO_TEST_CASE(strings)
BOOST_CHECK(callContractFunction(1, bytes({0x00, 0x02, 0x01})) == expectation); BOOST_CHECK(callContractFunction(1, bytes({0x00, 0x02, 0x01})) == expectation);
} }
BOOST_AUTO_TEST_CASE(empty_string_on_stack)
{
char const* sourceCode = "contract test {\n"
" function run(string0 empty, uint8 inp) returns(uint16 a, string0 b, string4 c) {\n"
" var x = \"abc\";\n"
" var y = \"\";\n"
" var z = inp;\n"
" a = z; b = y; c = x;"
" }\n"
"}\n";
compileAndRun(sourceCode);
BOOST_CHECK(callContractFunction(0, bytes({0x02})) == bytes({0x00, 0x02, 'a', 'b', 'c', 0x00}));
}
BOOST_AUTO_TEST_CASE(state_smoke_test) BOOST_AUTO_TEST_CASE(state_smoke_test)
{ {
char const* sourceCode = "contract test {\n" char const* sourceCode = "contract test {\n"

8
test/solidityNameAndTypeResolution.cpp

@ -226,14 +226,6 @@ BOOST_AUTO_TEST_CASE(type_inference_explicit_conversion)
BOOST_CHECK_NO_THROW(parseTextAndResolveNames(text)); BOOST_CHECK_NO_THROW(parseTextAndResolveNames(text));
} }
BOOST_AUTO_TEST_CASE(empty_string_literal)
{
char const* text = "contract test {\n"
" function f() { var x = \"\"; }"
"}\n";
BOOST_CHECK_THROW(parseTextAndResolveNames(text), TypeError);
}
BOOST_AUTO_TEST_CASE(large_string_literal) BOOST_AUTO_TEST_CASE(large_string_literal)
{ {
char const* text = "contract test {\n" char const* text = "contract test {\n"

Loading…
Cancel
Save