[bcl] Handle BigInt -> long conversions that should overflow but dont. Fixes #16526
authorRodrigo Kumpera <kumpera@gmail.com>
Fri, 6 Dec 2013 16:13:29 +0000 (11:13 -0500)
committerRodrigo Kumpera <kumpera@gmail.com>
Fri, 6 Dec 2013 16:13:29 +0000 (11:13 -0500)
mcs/class/System.Numerics/System.Numerics/BigInteger.cs
mcs/class/System.Numerics/Test/System.Numerics/BigIntegerTest.cs

index 816ca2ffceeb3a6a250e8b1f682e77919a3f658d..a05d403988bf87e95298ae18060194a7c037208b 100644 (file)
@@ -473,10 +473,20 @@ namespace System.Numerics {
                                return (((long)high) << 32) | low;
                        }
 
-                       if (high > 0x80000000u)
+                       /*
+                       We cannot represent negative numbers smaller than long.MinValue.
+                       Those values are encoded into what look negative numbers, so negating
+                       them produces a positive value, that's why it's safe to check for that
+                       condition.
+
+                       long.MinValue works fine since it's bigint encoding looks like a negative
+                       number, but since long.MinValue == -long.MinValue, we're good.
+                       */
+
+                       long result = - ((((long)high) << 32) | (long)low);
+                       if (result > 0)
                                throw new OverflowException ();
-
-                       return - ((((long)high) << 32) | (long)low);
+                       return result;
                }
 
                [CLSCompliantAttribute (false)]
index 098c50854b78f1be97ebd61df42710541e7ccbbc..a5ec016bb3ee37ce9b16e17e566b0ff36772416f 100644 (file)
@@ -1145,5 +1145,19 @@ namespace MonoTests.System.Numerics
                        a = new BigInteger ();
                        Assert.AreEqual (BigInteger.Zero.GetHashCode (), a.GetHashCode (), "#15");
                }
+
+               [Test]
+               public void Bug16526 ()
+               {
+                       var x = BigInteger.Pow(2, 63);
+                       x *= -1;
+                       x -= 1;
+                       Assert.AreEqual ("-9223372036854775809", x.ToString (), "#1");
+                       try {
+                               x = (long)x;
+                               Assert.Fail ("#2 Must OVF");
+                       } catch (OverflowException) {
+                       }
+               }
        }
 }