diff --git a/src/libraries/System.Runtime.Numerics/src/Properties/InternalsVisibleTo.cs b/src/libraries/System.Runtime.Numerics/src/Properties/InternalsVisibleTo.cs new file mode 100644 index 0000000000000..37afaaf1abfac --- /dev/null +++ b/src/libraries/System.Runtime.Numerics/src/Properties/InternalsVisibleTo.cs @@ -0,0 +1,6 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. + +using System.Runtime.CompilerServices; + +[assembly: InternalsVisibleTo("System.Runtime.Numerics.Tests, PublicKey=00240000048000009400000006020000002400005253413100040000010001004b86c4cb78549b34bab61a3b1800e23bfeb5b3ec390074041536a7e3cbd97f5f04cf0f857155a8928eaa29ebfd11cfbbad3ba70efea7bda3226c6a8d370a4cd303f714486b6ebc225985a638471e6ef571cc92a4613c00b8fa65d61ccee0cbe5f36330c9a01f4183559f1bef24cc2917c6d913e3a541333a1d05d9bed22b38cb")] diff --git a/src/libraries/System.Runtime.Numerics/src/System.Runtime.Numerics.csproj b/src/libraries/System.Runtime.Numerics/src/System.Runtime.Numerics.csproj index 5c2f63834c360..1de04876ac55a 100644 --- a/src/libraries/System.Runtime.Numerics/src/System.Runtime.Numerics.csproj +++ b/src/libraries/System.Runtime.Numerics/src/System.Runtime.Numerics.csproj @@ -25,6 +25,7 @@ Link="CoreLib\System\Text\ValueStringBuilder.cs" /> + diff --git a/src/libraries/System.Runtime.Numerics/src/System/Numerics/BigInteger.cs b/src/libraries/System.Runtime.Numerics/src/System/Numerics/BigInteger.cs index ad11be661d513..6b9fdcea40ca7 100644 --- a/src/libraries/System.Runtime.Numerics/src/System/Numerics/BigInteger.cs +++ b/src/libraries/System.Runtime.Numerics/src/System/Numerics/BigInteger.cs @@ -2211,7 +2211,7 @@ stackalloc uint[BigIntegerCalculator.StackAllocThreshold] if (negx) { - if (shift >= (kcbitUint * xd.Length)) + if (shift >= ((long)kcbitUint * xd.Length)) { result = MinusOne; goto exit; diff --git a/src/libraries/System.Runtime.Numerics/tests/BigInteger/op_rightshift.cs b/src/libraries/System.Runtime.Numerics/tests/BigInteger/op_rightshift.cs index 2f65e779c0430..da6ac2615b9c1 100644 --- a/src/libraries/System.Runtime.Numerics/tests/BigInteger/op_rightshift.cs +++ b/src/libraries/System.Runtime.Numerics/tests/BigInteger/op_rightshift.cs @@ -25,6 +25,54 @@ public static void BigShiftsTest() } } + [ConditionalFact(typeof(PlatformDetection), nameof(PlatformDetection.Is64BitProcess))] // May fail on 32-bit due to a large memory requirement + public static void LargeNegativeBigIntegerShiftTest() + { + // Create a very large negative BigInteger + BigInteger bigInt = new BigInteger(-1) << int.MaxValue; + Assert.Equal(2147483647, bigInt.GetBitLength()); + Assert.Equal(-1, bigInt.Sign); + + // Validate internal representation. + // At this point, bigInt should be a 1 followed by int.MaxValue zeros. + // Given this, bigInt._bits is expected to be structured as follows: + // - _bits.Length == (int.MaxValue + 1) / (8 * sizeof(uint)) + // - First (_bits.Length - 1) elements: 0x00000000 + // - Last element: 0x80000000 + // ^------ (There's the leading '1') + + Assert.Equal(((uint)int.MaxValue + 1) / (8 * sizeof(uint)), (uint)bigInt._bits.Length); + + uint i = 0; + for (; i < (bigInt._bits.Length - 1); i++) { + Assert.Equal(0x00000000u, bigInt._bits[i]); + } + + Assert.Equal(0x80000000u, bigInt._bits[i]); + + // Right shift the BigInteger + BigInteger shiftedBigInt = bigInt >> 1; + Assert.Equal(2147483646, shiftedBigInt.GetBitLength()); + Assert.Equal(-1, shiftedBigInt.Sign); + + // Validate internal representation. + // At this point, shiftedBigInt should be a 1 followed by int.MaxValue - 1 zeros. + // Given this, shiftedBigInt._bits is expected to be structured as follows: + // - _bits.Length == (int.MaxValue + 1) / (8 * sizeof(uint)) + // - First (_bits.Length - 1) elements: 0x00000000 + // - Last element: 0x40000000 + // ^------ (the '1' is now one position to the right) + + Assert.Equal(((uint)int.MaxValue + 1) / (8 * sizeof(uint)), (uint)shiftedBigInt._bits.Length); + + i = 0; + for (; i < (shiftedBigInt._bits.Length - 1); i++) { + Assert.Equal(0x00000000u, shiftedBigInt._bits[i]); + } + + Assert.Equal(0x40000000u, shiftedBigInt._bits[i]); + } + [Fact] public static void RunRightShiftTests() { diff --git a/src/libraries/System.Runtime.Numerics/tests/System.Runtime.Numerics.Tests.csproj b/src/libraries/System.Runtime.Numerics/tests/System.Runtime.Numerics.Tests.csproj index 3cd75b812f1eb..4b9dbea05bf6b 100644 --- a/src/libraries/System.Runtime.Numerics/tests/System.Runtime.Numerics.Tests.csproj +++ b/src/libraries/System.Runtime.Numerics/tests/System.Runtime.Numerics.Tests.csproj @@ -54,4 +54,8 @@ + + + +