Welcome to mirror list, hosted at ThFree Co, Russian Federation.

github.com/dotnet/runtime.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorTanner Gooding <tagoo@microsoft.com>2022-02-15 19:25:37 +0300
committerMatt Mitchell <mmitche@microsoft.com>2022-02-15 19:25:37 +0300
commit3065735be79d6b7d17e8e3a723115810b43c9b3a (patch)
tree560d5ec8dc053ae0e391bd1600f099714f6bd286
parentf4567ec9864f30f27f6672d882ea98db754149bb (diff)
Merged PR 21171: Fixing the shift-left handling to correctly account for overshiftingv5.0.15
Fixing the shift-left handling to correctly account for overshifting
-rw-r--r--src/libraries/System.Private.CoreLib/src/System/Number.BigInteger.cs44
1 files changed, 32 insertions, 12 deletions
diff --git a/src/libraries/System.Private.CoreLib/src/System/Number.BigInteger.cs b/src/libraries/System.Private.CoreLib/src/System/Number.BigInteger.cs
index ccea6055d7b..8c8d28c5880 100644
--- a/src/libraries/System.Private.CoreLib/src/System/Number.BigInteger.cs
+++ b/src/libraries/System.Private.CoreLib/src/System/Number.BigInteger.cs
@@ -31,7 +31,9 @@ namespace System
private const int MaxBits = BitsForLongestBinaryMantissa + BitsForLongestDigitSequence + BitsPerBlock;
private const int BitsPerBlock = sizeof(int) * 8;
- private const int MaxBlockCount = (MaxBits + (BitsPerBlock - 1)) / BitsPerBlock;
+
+ // We need one extra block to make our shift left algorithm significantly simpler
+ private const int MaxBlockCount = ((MaxBits + (BitsPerBlock - 1)) / BitsPerBlock) + 1;
private static readonly uint[] s_Pow10UInt32Table = new uint[]
{
@@ -302,7 +304,8 @@ namespace System
0xD9D61A05,
0x00000325,
- // 9 Trailing blocks to ensure MaxBlockCount
+ // 10 Trailing blocks to ensure MaxBlockCount
+ 0x00000000,
0x00000000,
0x00000000,
0x00000000,
@@ -1205,19 +1208,21 @@ namespace System
int readIndex = (length - 1);
int writeIndex = readIndex + (int)(blocksToShift);
- uint remainingBitsInLastBlock = (uint)BitOperations.LeadingZeroCount(_blocks[readIndex]);
-
- if (remainingBitsToShift > remainingBitsInLastBlock)
- {
- // We need an extra block for the partial shift
- writeIndex++;
- }
-
- Debug.Assert(unchecked((uint)(writeIndex)) < MaxBlockCount);
-
// Check if the shift is block aligned
if (remainingBitsToShift == 0)
{
+ Debug.Assert(unchecked((uint)(length)) < MaxBlockCount);
+
+ if (unchecked((uint)(length)) >= MaxBlockCount)
+ {
+ // We shouldn't reach here, and the above assert will help flag this
+ // during testing, but we'll ensure that we return a safe value of
+ // zero in the case we end up overflowing in any way.
+
+ SetZero(out this);
+ return;
+ }
+
while (readIndex >= 0)
{
_blocks[writeIndex] = _blocks[readIndex];
@@ -1232,6 +1237,21 @@ namespace System
}
else
{
+ // We need an extra block for the partial shift
+
+ writeIndex++;
+ Debug.Assert(unchecked((uint)(length)) < MaxBlockCount);
+
+ if (unchecked((uint)(length)) >= MaxBlockCount)
+ {
+ // We shouldn't reach here, and the above assert will help flag this
+ // during testing, but we'll ensure that we return a safe value of
+ // zero in the case we end up overflowing in any way.
+
+ SetZero(out this);
+ return;
+ }
+
// Set the length to hold the shifted blocks
_length = writeIndex + 1;