Merge pull request #9828 from ethereum/noUnsignedNegation

Restrict unary negation to signed integers.
This commit is contained in:
chriseth 2020-09-17 15:42:06 +02:00 committed by GitHub
commit e7e1f74678
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
6 changed files with 20 additions and 8 deletions

View File

@ -1,5 +1,7 @@
### 0.8.0 (unreleased)
Breaking Changes:
* Type System: Unary negation can only be used on signed integers, not on unsigned integers.
### 0.7.2 (unreleased)

View File

@ -38,7 +38,7 @@ Operators:
* Comparisons: ``<=``, ``<``, ``==``, ``!=``, ``>=``, ``>`` (evaluate to ``bool``)
* Bit operators: ``&``, ``|``, ``^`` (bitwise exclusive or), ``~`` (bitwise negation)
* Shift operators: ``<<`` (left shift), ``>>`` (right shift)
* Arithmetic operators: ``+``, ``-``, unary ``-``, ``*``, ``/``, ``%`` (modulo), ``**`` (exponentiation)
* Arithmetic operators: ``+``, ``-``, unary ``-`` (only for signed integers), ``*``, ``/``, ``%`` (modulo), ``**`` (exponentiation)
For an integer type ``X``, you can use ``type(X).min`` and ``type(X).max`` to
access the minimum and maximum value representable by the type.
@ -83,8 +83,8 @@ for example ``uint256(0) - uint256(1) == 2**256 - 1``. You have to take these ov
into account when designing safe smart contracts.
The expression ``-x`` is equivalent to ``(T(0) - x)`` where
``T`` is the type of ``x``. This means that ``-x`` will not be negative
if the type of ``x`` is an unsigned integer type. Also, ``-x`` can be
``T`` is the type of ``x``. It can only be applied to signed types.
The value of ``-x`` can be
positive if ``x`` is negative. There is another caveat also resulting
from two's complement representation::

View File

@ -627,9 +627,10 @@ TypeResult IntegerType::unaryOperatorResult(Token _operator) const
// "delete" is ok for all integer types
if (_operator == Token::Delete)
return TypeResult{TypeProvider::emptyTuple()};
// we allow -, ++ and --
else if (_operator == Token::Sub || _operator == Token::Inc ||
_operator == Token::Dec || _operator == Token::BitNot)
// unary negation only on signed types
else if (_operator == Token::Sub)
return isSigned() ? TypeResult{this} : TypeResult::err("Unary negation is only allowed for signed integers.");
else if (_operator == Token::Inc || _operator == Token::Dec || _operator == Token::BitNot)
return TypeResult{this};
else
return TypeResult::err("");

View File

@ -778,7 +778,7 @@ BOOST_AUTO_TEST_CASE(sign_extension)
function run() public returns(uint256 y) {
int64 x = -int32(0xff);
if (x >= 0xff) return 0;
return -uint256(x);
return 0 - uint256(x);
}
}
)";

View File

@ -9,7 +9,7 @@ contract C {
returns (uint256 x1, uint256 x2, uint256 x3, uint256 x4)
{
a = -2;
b = -uint8(a) * 2;
b = (0 - uint8(a)) * 2;
c = a * int8(120) * int8(121);
x1 = uint256(a);
x2 = b;

View File

@ -0,0 +1,9 @@
contract test {
function f() public pure {
int x;
uint y = uint(-x);
-y;
}
}
// ----
// TypeError 4907: (97-99): Unary operator - cannot be applied to type uint256