From e107d51f46cfbadc8137f8c2c942ff791727be04 Mon Sep 17 00:00:00 2001 From: hrkrshnn Date: Mon, 4 Jan 2021 12:06:03 +0100 Subject: [PATCH] Disallow certain implicit conversions between integer types. Disallow implicit conversion from ``uintN`` and ``intM`` when ``M > N``, and by extension, explicit conversion between the same types are also disallowed. --- Changelog.md | 1 + libsolidity/ast/Types.cpp | 9 +++++---- test/compilationTests/gnosis/Events/ScalarEvent.sol | 2 +- .../010_type_conversion_for_comparison.sol | 6 +++--- .../syntaxTests/types/integer_implicit_err.sol | 13 +++++++++++++ .../syntaxTests/types/strict_explicit.sol | 4 ++++ 6 files changed, 27 insertions(+), 8 deletions(-) create mode 100644 test/libsolidity/syntaxTests/types/integer_implicit_err.sol diff --git a/Changelog.md b/Changelog.md index 5866a946c..87fd0e907 100644 --- a/Changelog.md +++ b/Changelog.md @@ -14,6 +14,7 @@ Bugfixes: * SMTChecker: Fix false negatives when analyzing external function calls. * SMTChecker: Fix missing type constraints for block variables. * SMTChecker: Fix internal error on ``block.chainid``. + * Type System: Disallow implicit conversion from ``uintN`` to ``intM`` when ``M > N``, and by extension, explicit conversion between the same types is also disallowed. ### 0.8.0 (2020-12-16) diff --git a/libsolidity/ast/Types.cpp b/libsolidity/ast/Types.cpp index 349435115..7a236b3e3 100644 --- a/libsolidity/ast/Types.cpp +++ b/libsolidity/ast/Types.cpp @@ -508,12 +508,13 @@ BoolResult IntegerType::isImplicitlyConvertibleTo(Type const& _convertTo) const if (_convertTo.category() == category()) { IntegerType const& convertTo = dynamic_cast(_convertTo); - if (convertTo.m_bits < m_bits) + // disallowing unsigned to signed conversion of different bits + if (isSigned() != convertTo.isSigned()) + return false; + else if (convertTo.m_bits < m_bits) return false; - else if (isSigned()) - return convertTo.isSigned(); else - return !convertTo.isSigned() || convertTo.m_bits > m_bits; + return true; } else if (_convertTo.category() == Category::FixedPoint) { diff --git a/test/compilationTests/gnosis/Events/ScalarEvent.sol b/test/compilationTests/gnosis/Events/ScalarEvent.sol index f728c65e2..f918c822a 100644 --- a/test/compilationTests/gnosis/Events/ScalarEvent.sol +++ b/test/compilationTests/gnosis/Events/ScalarEvent.sol @@ -61,7 +61,7 @@ contract ScalarEvent is Event { convertedWinningOutcome = OUTCOME_RANGE; // Map outcome to outcome range else - convertedWinningOutcome = uint24(uint(OUTCOME_RANGE * (outcome - lowerBound) / (upperBound - lowerBound))); + convertedWinningOutcome = uint24(uint(int(uint(OUTCOME_RANGE)) * (outcome - lowerBound) / (upperBound - lowerBound))); uint factorShort = OUTCOME_RANGE - convertedWinningOutcome; uint factorLong = OUTCOME_RANGE - factorShort; uint shortOutcomeTokenCount = outcomeTokens[SHORT].balanceOf(msg.sender); diff --git a/test/libsolidity/syntaxTests/nameAndTypeResolution/010_type_conversion_for_comparison.sol b/test/libsolidity/syntaxTests/nameAndTypeResolution/010_type_conversion_for_comparison.sol index 1e556408b..2dcd2ab69 100644 --- a/test/libsolidity/syntaxTests/nameAndTypeResolution/010_type_conversion_for_comparison.sol +++ b/test/libsolidity/syntaxTests/nameAndTypeResolution/010_type_conversion_for_comparison.sol @@ -1,6 +1,6 @@ contract test { - function f() public { uint32(2) == int64(2); } + function f() public { uint32(2) == uint64(2); } } // ---- -// Warning 6133: (42-63): Statement has no effect. -// Warning 2018: (20-66): Function state mutability can be restricted to pure +// Warning 6133: (42-64): Statement has no effect. +// Warning 2018: (20-67): Function state mutability can be restricted to pure diff --git a/test/libsolidity/syntaxTests/types/integer_implicit_err.sol b/test/libsolidity/syntaxTests/types/integer_implicit_err.sol new file mode 100644 index 000000000..5b99005c4 --- /dev/null +++ b/test/libsolidity/syntaxTests/types/integer_implicit_err.sol @@ -0,0 +1,13 @@ +contract C +{ + function f() public pure { + uint16 a = 1; + int32 b = a; + + uint256 c = 10; + int8 d = c; + } +} +// ---- +// TypeError 9574: (74-85): Type uint16 is not implicitly convertible to expected type int32. +// TypeError 9574: (120-130): Type uint256 is not implicitly convertible to expected type int8. diff --git a/test/libsolidity/syntaxTests/types/strict_explicit.sol b/test/libsolidity/syntaxTests/types/strict_explicit.sol index d2b67c891..8bfebb13d 100644 --- a/test/libsolidity/syntaxTests/types/strict_explicit.sol +++ b/test/libsolidity/syntaxTests/types/strict_explicit.sol @@ -37,6 +37,10 @@ contract C B n = B(address(uint160(uint(int(100))))); n; + + uint8 o = 1; + int16 p = int16(o); } } // ---- +// TypeError 9640: (801-809): Explicit type conversion not allowed from "uint8" to "int16".