Explorar el Código

Fix type(int256).min in comparisons (#1527)

When resolving comparisons, we don't know what the types of the operands
are so we resolve with `ResolveTo::Unknown`. In this path, there is an
mistake in the bounds check for negative integers.

Fixes https://github.com/hyperledger/solang/issues/1523

Signed-off-by: Sean Young <sean@mess.org>
Sean Young hace 2 años
padre
commit
febdd6f1dc

+ 8 - 2
src/sema/expression/integers.rs

@@ -188,8 +188,6 @@ pub fn bigint_to_expression(
     resolve_to: ResolveTo,
     resolve_to: ResolveTo,
     hex_str_len: Option<usize>,
     hex_str_len: Option<usize>,
 ) -> Result<Expression, ()> {
 ) -> Result<Expression, ()> {
-    let bits = n.bits();
-
     if let ResolveTo::Type(resolve_to) = resolve_to {
     if let ResolveTo::Type(resolve_to) = resolve_to {
         if *resolve_to != Type::Unresolved {
         if *resolve_to != Type::Unresolved {
             if !(resolve_to.is_integer(ns) || matches!(resolve_to, Type::Bytes(_)) && n.is_zero()) {
             if !(resolve_to.is_integer(ns) || matches!(resolve_to, Type::Bytes(_)) && n.is_zero()) {
@@ -208,6 +206,14 @@ pub fn bigint_to_expression(
         }
         }
     }
     }
 
 
+    // BigInt bits() returns the bits used without the sign. Negative value is allowed to be one
+    // larger than positive value, e.g int8 has inclusive range -128 to 127.
+    let bits = if n.sign() == Sign::Minus {
+        (n + 1u32).bits()
+    } else {
+        n.bits()
+    };
+
     // Return smallest type; hex literals with odd length are not allowed.
     // Return smallest type; hex literals with odd length are not allowed.
     let int_size = hex_str_len
     let int_size = hex_str_len
         .map(|v| if v % 2 == 0 { v as u64 * 4 } else { bits })
         .map(|v| if v % 2 == 0 { v as u64 * 4 } else { bits })

+ 31 - 0
tests/contract_testcases/solana/large_negative_ints.sol

@@ -0,0 +1,31 @@
+pragma solidity ^0.8.0;
+
+library Issue1523 {
+    function i1523_fail1(int256 x) internal pure returns (bool) {
+        return x <= type(int256).min;
+    }
+
+    function i1523_fail2(int256 x) internal pure returns (bool) {
+        return x <= type(int256).min + 1;
+    }
+
+    function i1523_fail3(int256 x) internal pure returns (bool) {
+        // Actual min value inlined
+        return x <= -57896044618658097711785492504343953926634992332820282019728792003956564819968;
+    }
+
+    function i1523_fail4(int256 x) internal pure returns (bool) {
+        // Actual min value + 1
+        return x <= -57896044618658097711785492504343953926634992332820282019728792003956564819967;
+    }
+
+    function i1523_pass1() internal pure returns (int256) {
+        return type(int256).min + 1;
+    }
+
+    function i1523_pass2() internal pure returns (int256) {
+        return type(int256).min;
+    }
+}
+
+// ---- Expect: diagnostics ----