Skip to content

Commit 023fd99

Browse files
authored
Merge pull request #66353 from vseanreesermsft/internal-merge-6.0-2022-03-08-1138
Merging internal commits for release/6.0
2 parents 10b1751 + 292c12b commit 023fd99

File tree

2 files changed

+107
-15
lines changed

2 files changed

+107
-15
lines changed

eng/pipelines/runtime-official.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -386,7 +386,7 @@ stages:
386386
jobParameters:
387387
isOfficialBuild: ${{ variables.isOfficialBuild }}
388388
liveRuntimeBuildConfig: release
389-
liveLibrariesBuildConfig: ${{ variables.debugOnPrReleaseOnRolling }}
389+
liveLibrariesBuildConfig: Release
390390
pgoType: 'PGO'
391391
platforms:
392392
- windows_x64

src/libraries/System.Private.CoreLib/src/System/Number.BigInteger.cs

Lines changed: 106 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -31,7 +31,9 @@ internal unsafe ref struct BigInteger
3131
private const int MaxBits = BitsForLongestBinaryMantissa + BitsForLongestDigitSequence + BitsPerBlock;
3232

3333
private const int BitsPerBlock = sizeof(int) * 8;
34-
private const int MaxBlockCount = (MaxBits + (BitsPerBlock - 1)) / BitsPerBlock;
34+
35+
// We need one extra block to make our shift left algorithm significantly simpler
36+
private const int MaxBlockCount = ((MaxBits + (BitsPerBlock - 1)) / BitsPerBlock) + 1;
3537

3638
private static readonly uint[] s_Pow10UInt32Table = new uint[]
3739
{
@@ -302,7 +304,8 @@ internal unsafe ref struct BigInteger
302304
0xD9D61A05,
303305
0x00000325,
304306

305-
// 9 Trailing blocks to ensure MaxBlockCount
307+
// 10 Trailing blocks to ensure MaxBlockCount
308+
0x00000000,
306309
0x00000000,
307310
0x00000000,
308311
0x00000000,
@@ -358,11 +361,24 @@ public static void Add(ref BigInteger lhs, ref BigInteger rhs, out BigInteger re
358361
resultIndex++;
359362
}
360363

364+
int resultLength = largeLength;
365+
361366
// If there's still a carry, append a new block
362367
if (carry != 0)
363368
{
364369
Debug.Assert(carry == 1);
365-
Debug.Assert((resultIndex == largeLength) && (largeLength < MaxBlockCount));
370+
Debug.Assert(resultIndex == resultLength);
371+
Debug.Assert(unchecked((uint)(resultLength)) < MaxBlockCount);
372+
373+
if (unchecked((uint)(resultLength)) >= MaxBlockCount)
374+
{
375+
// We shouldn't reach here, and the above assert will help flag this
376+
// during testing, but we'll ensure that we return a safe value of
377+
// zero in the case we end up overflowing in any way.
378+
379+
SetZero(out result);
380+
return;
381+
}
366382

367383
result._blocks[resultIndex] = 1;
368384
result._length++;
@@ -722,16 +738,27 @@ public static void Multiply(ref BigInteger lhs, uint value, out BigInteger resul
722738
index++;
723739
}
724740

741+
int resultLength = lhsLength;
742+
725743
if (carry != 0)
726744
{
727-
Debug.Assert(unchecked((uint)(lhsLength)) + 1 <= MaxBlockCount);
745+
Debug.Assert(unchecked((uint)(resultLength)) < MaxBlockCount);
746+
747+
if (unchecked((uint)(resultLength)) >= MaxBlockCount)
748+
{
749+
// We shouldn't reach here, and the above assert will help flag this
750+
// during testing, but we'll ensure that we return a safe value of
751+
// zero in the case we end up overflowing in any way.
752+
753+
SetZero(out result);
754+
return;
755+
}
756+
728757
result._blocks[index] = carry;
729-
result._length = (lhsLength + 1);
730-
}
731-
else
732-
{
733-
result._length = lhsLength;
758+
resultLength += 1;
734759
}
760+
761+
result._length = resultLength;
735762
}
736763

737764
public static void Multiply(ref BigInteger lhs, ref BigInteger rhs, out BigInteger result)
@@ -766,6 +793,16 @@ public static void Multiply(ref BigInteger lhs, ref BigInteger rhs, out BigInteg
766793
int maxResultLength = smallLength + largeLength;
767794
Debug.Assert(unchecked((uint)(maxResultLength)) <= MaxBlockCount);
768795

796+
if (unchecked((uint)(maxResultLength)) > MaxBlockCount)
797+
{
798+
// We shouldn't reach here, and the above assert will help flag this
799+
// during testing, but we'll ensure that we return a safe value of
800+
// zero in the case we end up overflowing in any way.
801+
802+
SetZero(out result);
803+
return;
804+
}
805+
769806
// Zero out result internal blocks.
770807
result._length = maxResultLength;
771808
result.Clear((uint)maxResultLength);
@@ -811,7 +848,19 @@ public static void Pow2(uint exponent, out BigInteger result)
811848
{
812849
uint blocksToShift = DivRem32(exponent, out uint remainingBitsToShift);
813850
result._length = (int)blocksToShift + 1;
851+
814852
Debug.Assert(unchecked((uint)result._length) <= MaxBlockCount);
853+
854+
if (unchecked((uint)result._length) > MaxBlockCount)
855+
{
856+
// We shouldn't reach here, and the above assert will help flag this
857+
// during testing, but we'll ensure that we return a safe value of
858+
// zero in the case we end up overflowing in any way.
859+
860+
SetZero(out result);
861+
return;
862+
}
863+
815864
if (blocksToShift > 0)
816865
{
817866
result.Clear(blocksToShift);
@@ -1001,7 +1050,18 @@ public void Add(uint value)
10011050
}
10021051
}
10031052

1004-
Debug.Assert(unchecked((uint)(length)) + 1 <= MaxBlockCount);
1053+
Debug.Assert(unchecked((uint)(length)) < MaxBlockCount);
1054+
1055+
if (unchecked((uint)(length)) >= MaxBlockCount)
1056+
{
1057+
// We shouldn't reach here, and the above assert will help flag this
1058+
// during testing, but we'll ensure that we return a safe value of
1059+
// zero in the case we end up overflowing in any way.
1060+
1061+
SetZero(out this);
1062+
return;
1063+
}
1064+
10051065
_blocks[length] = 1;
10061066
_length = length + 1;
10071067
}
@@ -1063,9 +1123,20 @@ public void Multiply10()
10631123

10641124
if (carry != 0)
10651125
{
1066-
Debug.Assert(unchecked((uint)(_length)) + 1 <= MaxBlockCount);
1126+
Debug.Assert(unchecked((uint)(length)) < MaxBlockCount);
1127+
1128+
if (unchecked((uint)(length)) >= MaxBlockCount)
1129+
{
1130+
// We shouldn't reach here, and the above assert will help flag this
1131+
// during testing, but we'll ensure that we return a safe value of
1132+
// zero in the case we end up overflowing in any way.
1133+
1134+
SetZero(out this);
1135+
return;
1136+
}
1137+
10671138
_blocks[index] = (uint)carry;
1068-
_length++;
1139+
_length = length + 1;
10691140
}
10701141
}
10711142

@@ -1141,7 +1212,17 @@ public void ShiftLeft(uint shift)
11411212
// Check if the shift is block aligned
11421213
if (remainingBitsToShift == 0)
11431214
{
1144-
Debug.Assert(writeIndex < MaxBlockCount);
1215+
Debug.Assert(unchecked((uint)(length)) < MaxBlockCount);
1216+
1217+
if (unchecked((uint)(length)) >= MaxBlockCount)
1218+
{
1219+
// We shouldn't reach here, and the above assert will help flag this
1220+
// during testing, but we'll ensure that we return a safe value of
1221+
// zero in the case we end up overflowing in any way.
1222+
1223+
SetZero(out this);
1224+
return;
1225+
}
11451226

11461227
while (readIndex >= 0)
11471228
{
@@ -1158,8 +1239,19 @@ public void ShiftLeft(uint shift)
11581239
else
11591240
{
11601241
// We need an extra block for the partial shift
1242+
11611243
writeIndex++;
1162-
Debug.Assert(writeIndex < MaxBlockCount);
1244+
Debug.Assert(unchecked((uint)(length)) < MaxBlockCount);
1245+
1246+
if (unchecked((uint)(length)) >= MaxBlockCount)
1247+
{
1248+
// We shouldn't reach here, and the above assert will help flag this
1249+
// during testing, but we'll ensure that we return a safe value of
1250+
// zero in the case we end up overflowing in any way.
1251+
1252+
SetZero(out this);
1253+
return;
1254+
}
11631255

11641256
// Set the length to hold the shifted blocks
11651257
_length = writeIndex + 1;

0 commit comments

Comments
 (0)