From 64408a9173e8ca2a575e88aef8abf6de870bfca1 Mon Sep 17 00:00:00 2001 From: chriseth Date: Tue, 17 Aug 2021 15:57:02 +0200 Subject: [PATCH] Disallow bare fractional literals that incur precision loss. --- libsolidity/ast/Types.cpp | 12 +++++++----- libsolidity/ast/Types.h | 2 +- 2 files changed, 8 insertions(+), 6 deletions(-) diff --git a/libsolidity/ast/Types.cpp b/libsolidity/ast/Types.cpp index 3d541401c..541374407 100644 --- a/libsolidity/ast/Types.cpp +++ b/libsolidity/ast/Types.cpp @@ -1030,7 +1030,7 @@ TypeResult RationalNumberType::binaryOperatorResult(Token _operator, Type const* { if (_other->category() == Category::Integer || _other->category() == Category::FixedPoint) { - if (isFractional() && !fixedPointType()) + if (isFractional() && !mobileType()) return TypeResult::err("Literal too large or cannot be represented without precision loss."); else if (!isFractional() && !integerType()) return TypeResult::err("Literal too large."); @@ -1143,7 +1143,7 @@ u256 RationalNumberType::literalValue(Literal const*) const shiftedValue = m_value.numerator(); else { - auto fixed = fixedPointType(); + auto fixed = closestFixedPointType(); solAssert(fixed, "Rational number cannot be represented as fixed point type."); unsigned fractionalDigits = fixed->fractionalDigits(); shiftedValue = m_value.numerator() * boost::multiprecision::pow(bigint(10), fractionalDigits) / m_value.denominator(); @@ -1164,8 +1164,10 @@ Type const* RationalNumberType::mobileType() const { if (!isFractional()) return integerType(); - else - return fixedPointType(); + else if (auto const* fixed = closestFixedPointType()) + if (isImplicitlyConvertibleTo(*fixed)) + return fixed; + return nullptr; } IntegerType const* RationalNumberType::integerType() const @@ -1184,7 +1186,7 @@ IntegerType const* RationalNumberType::integerType() const ); } -FixedPointType const* RationalNumberType::fixedPointType() const +FixedPointType const* RationalNumberType::closestFixedPointType() const { bool negative = (m_value < 0); unsigned fractionalDigits = 0; diff --git a/libsolidity/ast/Types.h b/libsolidity/ast/Types.h index 38c9ba663..af08c90db 100644 --- a/libsolidity/ast/Types.h +++ b/libsolidity/ast/Types.h @@ -580,7 +580,7 @@ public: /// If the integer part does not fit, returns an empty pointer. /// The rational number is not always implicitly convertible to the resulting type /// (for example if precision loss is required). - FixedPointType const* fixedPointType() const; + FixedPointType const* closestFixedPointType() const; /// @returns true if the value is not an integer. bool isFractional() const { return m_value.denominator() != 1; }