From b535b6a55336ba9c03d4e8967c7fd15ab1a5d9cc Mon Sep 17 00:00:00 2001 From: Rodrigo Kumpera Date: Fri, 6 Dec 2013 11:13:29 -0500 Subject: [PATCH] [bcl] Handle BigInt -> long conversions that should overflow but dont. Fixes #16526 --- .../System.Numerics/BigInteger.cs | 16 +++++++++++++--- .../Test/System.Numerics/BigIntegerTest.cs | 14 ++++++++++++++ 2 files changed, 27 insertions(+), 3 deletions(-) diff --git a/mcs/class/System.Numerics/System.Numerics/BigInteger.cs b/mcs/class/System.Numerics/System.Numerics/BigInteger.cs index 816ca2ffcee..a05d403988b 100644 --- a/mcs/class/System.Numerics/System.Numerics/BigInteger.cs +++ b/mcs/class/System.Numerics/System.Numerics/BigInteger.cs @@ -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)] diff --git a/mcs/class/System.Numerics/Test/System.Numerics/BigIntegerTest.cs b/mcs/class/System.Numerics/Test/System.Numerics/BigIntegerTest.cs index 098c50854b7..a5ec016bb3e 100644 --- a/mcs/class/System.Numerics/Test/System.Numerics/BigIntegerTest.cs +++ b/mcs/class/System.Numerics/Test/System.Numerics/BigIntegerTest.cs @@ -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) { + } + } } } -- 2.25.1