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 @@
+
+
+
+