From a90ec7576c5afb646af809bc7aa7b22fd892f87b Mon Sep 17 00:00:00 2001 From: Christian Date: Fri, 6 Feb 2015 13:38:10 +0100 Subject: [PATCH] Some fixes for the ether units parser. --- libsolidity/AST.cpp | 11 ------- libsolidity/AST.h | 3 +- libsolidity/Parser.cpp | 16 +++++++--- libsolidity/Types.cpp | 44 ++++++++++++-------------- libsolidity/Types.h | 3 +- test/SolidityNameAndTypeResolution.cpp | 22 +++++++++++++ test/SolidityParser.cpp | 13 ++++++++ 7 files changed, 69 insertions(+), 43 deletions(-) diff --git a/libsolidity/AST.cpp b/libsolidity/AST.cpp index 156d51f24..0ec0eb0cc 100644 --- a/libsolidity/AST.cpp +++ b/libsolidity/AST.cpp @@ -596,17 +596,6 @@ void ElementaryTypeNameExpression::checkTypeRequirements() m_type = make_shared(Type::fromElementaryTypeName(m_typeToken)); } -Literal::Literal(Location const& _location, Token::Value _token, - ASTPointer const& _value, - Token::Value _sub): - PrimaryExpression(_location), m_token(_token), m_value(_value) -{ - if (Token::isEtherSubdenomination(_sub)) - m_subDenomination = static_cast(_sub); - else - m_subDenomination = Literal::SubDenomination::None; -} - void Literal::checkTypeRequirements() { m_type = Type::forLiteral(*this); diff --git a/libsolidity/AST.h b/libsolidity/AST.h index bced99f9a..47f2a40ca 100755 --- a/libsolidity/AST.h +++ b/libsolidity/AST.h @@ -1127,7 +1127,8 @@ public: }; Literal(Location const& _location, Token::Value _token, ASTPointer const& _value, - Token::Value _sub = Token::ILLEGAL); + SubDenomination _sub = SubDenomination::None): + PrimaryExpression(_location), m_token(_token), m_value(_value), m_subDenomination(_sub) {} virtual void accept(ASTVisitor& _visitor) override; virtual void accept(ASTConstVisitor& _visitor) const override; virtual void checkTypeRequirements() override; diff --git a/libsolidity/Parser.cpp b/libsolidity/Parser.cpp index 741b9aba7..d8c15c36d 100644 --- a/libsolidity/Parser.cpp +++ b/libsolidity/Parser.cpp @@ -684,7 +684,6 @@ ASTPointer Parser::parsePrimaryExpression() ASTNodeFactory nodeFactory(*this); Token::Value token = m_scanner->getCurrentToken(); ASTPointer expression; - Token::Value nextToken = Token::ILLEGAL; switch (token) { case Token::TRUE_LITERAL: @@ -692,12 +691,19 @@ ASTPointer Parser::parsePrimaryExpression() expression = nodeFactory.createNode(token, getLiteralAndAdvance()); break; case Token::NUMBER: - nextToken = m_scanner->peekNextToken(); + if (Token::isEtherSubdenomination(m_scanner->peekNextToken())) + { + ASTPointer literal = getLiteralAndAdvance(); + nodeFactory.markEndPosition(); + Literal::SubDenomination subdenomination = static_cast(m_scanner->getCurrentToken()); + m_scanner->next(); + expression = nodeFactory.createNode(token, literal, subdenomination); + break; + } + // fall-through case Token::STRING_LITERAL: nodeFactory.markEndPosition(); - expression = nodeFactory.createNode(token, getLiteralAndAdvance(), nextToken); - if (Token::isEtherSubdenomination(nextToken)) - m_scanner->next(); + expression = nodeFactory.createNode(token, getLiteralAndAdvance()); break; case Token::IDENTIFIER: nodeFactory.markEndPosition(); diff --git a/libsolidity/Types.cpp b/libsolidity/Types.cpp index 648cf9cb2..385495947 100644 --- a/libsolidity/Types.cpp +++ b/libsolidity/Types.cpp @@ -91,7 +91,7 @@ shared_ptr Type::forLiteral(Literal const& _literal) case Token::FALSE_LITERAL: return make_shared(); case Token::NUMBER: - return IntegerConstantType::fromLiteral(_literal.getValue()); + return make_shared(_literal); case Token::STRING_LITERAL: //@todo put larger strings into dynamic strings return StaticStringType::smallestTypeForLiteral(_literal.getValue()); @@ -216,9 +216,25 @@ const MemberList IntegerType::AddressMemberList = strings{}, FunctionType::Location::BARE)}, {"send", make_shared(strings{"uint"}, strings{}, FunctionType::Location::SEND)}}); -shared_ptr IntegerConstantType::fromLiteral(string const& _literal) +IntegerConstantType::IntegerConstantType(Literal const& _literal) { - return make_shared(bigint(_literal)); + m_value = bigint(_literal.getValue()); + + switch (_literal.getSubDenomination()) + { + case Literal::SubDenomination::Wei: + case Literal::SubDenomination::None: + break; + case Literal::SubDenomination::Szabo: + m_value *= bigint("1000000000000"); + break; + case Literal::SubDenomination::Finney: + m_value *= bigint("1000000000000000"); + break; + case Literal::SubDenomination::Ether: + m_value *= bigint("1000000000000000000"); + break; + } } bool IntegerConstantType::isImplicitlyConvertibleTo(Type const& _convertTo) const @@ -326,7 +342,7 @@ string IntegerConstantType::toString() const return "int_const " + m_value.str(); } -u256 IntegerConstantType::literalValue(Literal const* _literal) const +u256 IntegerConstantType::literalValue(Literal const*) const { u256 value; // we ignore the literal and hope that the type was correctly determined @@ -338,26 +354,6 @@ u256 IntegerConstantType::literalValue(Literal const* _literal) const else value = s2u(s256(m_value)); - if (_literal) - { - Literal::SubDenomination sub =_literal->getSubDenomination(); - switch(sub) - { - case Literal::SubDenomination::Wei: - case Literal::SubDenomination::None: - break; - case Literal::SubDenomination::Szabo: - value *= u256(1000000000000); - break; - case Literal::SubDenomination::Finney: - value *= u256(1000000000000000); - break; - case Literal::SubDenomination::Ether: - value *= u256(1000000000000000000); - break; - } - } - return value; } diff --git a/libsolidity/Types.h b/libsolidity/Types.h index 1f4d27a25..fcc77fea9 100644 --- a/libsolidity/Types.h +++ b/libsolidity/Types.h @@ -197,8 +197,7 @@ class IntegerConstantType: public Type public: virtual Category getCategory() const override { return Category::INTEGER_CONSTANT; } - static std::shared_ptr fromLiteral(std::string const& _literal); - + explicit IntegerConstantType(Literal const& _literal); explicit IntegerConstantType(bigint _value): m_value(_value) {} virtual bool isImplicitlyConvertibleTo(Type const& _convertTo) const override; diff --git a/test/SolidityNameAndTypeResolution.cpp b/test/SolidityNameAndTypeResolution.cpp index 742d2ee2a..05ce6ed66 100644 --- a/test/SolidityNameAndTypeResolution.cpp +++ b/test/SolidityNameAndTypeResolution.cpp @@ -910,6 +910,28 @@ BOOST_AUTO_TEST_CASE(disallow_declaration_of_void_type) BOOST_CHECK_THROW(parseTextAndResolveNames(sourceCode), TypeError); } +BOOST_AUTO_TEST_CASE(overflow_caused_by_ether_units) +{ + char const* sourceCodeFine = R"( + contract c { + function c () + { + a = 115792089237316195423570985008687907853269984665640564039458; + } + uint256 a; + })"; + BOOST_CHECK_NO_THROW(parseTextAndResolveNames(sourceCodeFine)); + char const* sourceCode = R"( + contract c { + function c () + { + a = 115792089237316195423570985008687907853269984665640564039458 ether; + } + uint256 a; + })"; + BOOST_CHECK_THROW(parseTextAndResolveNames(sourceCode), TypeError); +} + BOOST_AUTO_TEST_SUITE_END() } diff --git a/test/SolidityParser.cpp b/test/SolidityParser.cpp index b6837866c..7af99567b 100644 --- a/test/SolidityParser.cpp +++ b/test/SolidityParser.cpp @@ -679,6 +679,19 @@ BOOST_AUTO_TEST_CASE(literal_constants_with_ether_subdenominations) BOOST_CHECK_NO_THROW(parseTextExplainError(text)); } +BOOST_AUTO_TEST_CASE(literal_constants_with_ether_subdenominations_in_expressions) +{ + char const* text = R"( + contract c { + function c () + { + a = 1 wei * 100 wei + 7 szabo - 3; + } + uint256 a; + })"; + BOOST_CHECK_NO_THROW(parseTextExplainError(text)); +} + BOOST_AUTO_TEST_SUITE_END() }