@@ -353,18 +353,33 @@ public static void Add(ref BigInteger lhs, uint value, ref BigInteger result)
353
353
while ( index < lhsLength )
354
354
{
355
355
ulong sum = ( ulong ) ( lhs . _blocks [ index ] ) + carry ;
356
- lhs . _blocks [ index ] = ( uint ) ( sum ) ;
356
+ result . _blocks [ index ] = ( uint ) ( sum ) ;
357
357
carry = ( uint ) ( sum >> 32 ) ;
358
358
359
359
index ++ ;
360
360
}
361
361
362
+ int resultLength = lhsLength ;
363
+
362
364
if ( carry != 0 )
363
365
{
364
- Debug . Assert ( unchecked ( ( uint ) ( lhsLength ) ) + 1 <= MaxBlockCount ) ;
366
+ Debug . Assert ( unchecked ( ( uint ) ( resultLength ) ) < MaxBlockCount ) ;
367
+
368
+ if ( unchecked ( ( uint ) ( resultLength ) ) >= MaxBlockCount )
369
+ {
370
+ // We shouldn't reach here, and the above assert will help flag this
371
+ // during testing, but we'll ensure that we return a safe value of
372
+ // zero in the case we end up overflowing in any way.
373
+
374
+ result . SetZero ( ) ;
375
+ return ;
376
+ }
377
+
365
378
result . _blocks [ index ] = carry ;
366
- result . _length = ( lhsLength + 1 ) ;
379
+ resultLength += 1 ;
367
380
}
381
+
382
+ result . _length = resultLength ;
368
383
}
369
384
370
385
public static void Add ( ref BigInteger lhs , ref BigInteger rhs , out BigInteger result )
@@ -409,15 +424,30 @@ public static void Add(ref BigInteger lhs, ref BigInteger rhs, out BigInteger re
409
424
resultIndex ++ ;
410
425
}
411
426
427
+ int resultLength = largeLength ;
428
+
412
429
// If there's still a carry, append a new block
413
430
if ( carry != 0 )
414
431
{
415
432
Debug . Assert ( carry == 1 ) ;
416
- Debug . Assert ( ( resultIndex == largeLength ) && ( largeLength < MaxBlockCount ) ) ;
433
+ Debug . Assert ( resultIndex == resultLength ) ;
434
+ Debug . Assert ( unchecked ( ( uint ) ( resultLength ) ) < MaxBlockCount ) ;
435
+
436
+ if ( unchecked ( ( uint ) ( resultLength ) ) >= MaxBlockCount )
437
+ {
438
+ // We shouldn't reach here, and the above assert will help flag this
439
+ // during testing, but we'll ensure that we return a safe value of
440
+ // zero in the case we end up overflowing in any way.
441
+
442
+ result . SetZero ( ) ;
443
+ return ;
444
+ }
417
445
418
446
result . _blocks [ resultIndex ] = 1 ;
419
- result . _length += 1 ;
447
+ resultLength += 1 ;
420
448
}
449
+
450
+ result . _length = resultLength ;
421
451
}
422
452
423
453
public static int Compare ( ref BigInteger lhs , ref BigInteger rhs )
@@ -765,12 +795,27 @@ public static void Multiply(ref BigInteger lhs, uint value, ref BigInteger resul
765
795
index ++ ;
766
796
}
767
797
798
+ int resultLength = lhsLength ;
799
+
768
800
if ( carry != 0 )
769
801
{
770
- Debug . Assert ( unchecked ( ( uint ) ( lhsLength ) ) + 1 <= MaxBlockCount ) ;
802
+ Debug . Assert ( unchecked ( ( uint ) ( resultLength ) ) < MaxBlockCount ) ;
803
+
804
+ if ( unchecked ( ( uint ) ( resultLength ) ) >= MaxBlockCount )
805
+ {
806
+ // We shouldn't reach here, and the above assert will help flag this
807
+ // during testing, but we'll ensure that we return a safe value of
808
+ // zero in the case we end up overflowing in any way.
809
+
810
+ result . SetZero ( ) ;
811
+ return ;
812
+ }
813
+
771
814
result . _blocks [ index ] = carry ;
772
- result . _length = ( lhsLength + 1 ) ;
815
+ resultLength += 1 ;
773
816
}
817
+
818
+ result . _length = resultLength ;
774
819
}
775
820
776
821
public static void Multiply ( ref BigInteger lhs , ref BigInteger rhs , ref BigInteger result )
@@ -804,6 +849,16 @@ public static void Multiply(ref BigInteger lhs, ref BigInteger rhs, ref BigInteg
804
849
805
850
int maxResultLength = smallLength + largeLength ;
806
851
Debug . Assert ( unchecked ( ( uint ) ( maxResultLength ) ) <= MaxBlockCount ) ;
852
+
853
+ if ( unchecked ( ( uint ) ( maxResultLength ) ) > MaxBlockCount )
854
+ {
855
+ // We shouldn't reach here, and the above assert will help flag this
856
+ // during testing, but we'll ensure that we return a safe value of
857
+ // zero in the case we end up overflowing in any way.
858
+
859
+ result . SetZero ( ) ;
860
+ return ;
861
+ }
807
862
808
863
// Zero out result internal blocks.
809
864
Buffer . ZeroMemory ( ( byte * ) ( result . GetBlocksPointer ( ) ) , ( maxResultLength * sizeof ( uint ) ) ) ;
@@ -1072,6 +1127,18 @@ public void ExtendBlock(uint blockValue)
1072
1127
{
1073
1128
_blocks [ _length ] = blockValue ;
1074
1129
_length ++ ;
1130
+
1131
+ Debug . Assert ( unchecked ( ( uint ) ( _length ) ) <= MaxBlockCount ) ;
1132
+
1133
+ if ( unchecked ( ( uint ) ( _length ) ) > MaxBlockCount )
1134
+ {
1135
+ // We shouldn't reach here, and the above assert will help flag this
1136
+ // during testing, but we'll ensure that we return a safe value of
1137
+ // zero in the case we end up overflowing in any way.
1138
+
1139
+ SetZero ( ) ;
1140
+ return ;
1141
+ }
1075
1142
}
1076
1143
1077
1144
public void ExtendBlocks ( uint blockValue , uint blockCount )
@@ -1081,7 +1148,19 @@ public void ExtendBlocks(uint blockValue, uint blockCount)
1081
1148
if ( blockCount == 1 )
1082
1149
{
1083
1150
ExtendBlock ( blockValue ) ;
1151
+ return ;
1152
+ }
1084
1153
1154
+ int resultLength = _length + ( int ) ( blockCount ) ;
1155
+ Debug . Assert ( unchecked ( ( uint ) ( resultLength ) ) <= MaxBlockCount ) ;
1156
+
1157
+ if ( unchecked ( ( uint ) ( resultLength ) ) > MaxBlockCount )
1158
+ {
1159
+ // We shouldn't reach here, and the above assert will help flag this
1160
+ // during testing, but we'll ensure that we return a safe value of
1161
+ // zero in the case we end up overflowing in any way.
1162
+
1163
+ SetZero ( ) ;
1085
1164
return ;
1086
1165
}
1087
1166
@@ -1149,9 +1228,20 @@ public void Multiply10()
1149
1228
1150
1229
if ( carry != 0 )
1151
1230
{
1152
- Debug . Assert ( unchecked ( ( uint ) ( _length ) ) + 1 <= MaxBlockCount ) ;
1231
+ Debug . Assert ( unchecked ( ( uint ) ( length ) ) < MaxBlockCount ) ;
1232
+
1233
+ if ( unchecked ( ( uint ) ( length ) ) >= MaxBlockCount )
1234
+ {
1235
+ // We shouldn't reach here, and the above assert will help flag this
1236
+ // during testing, but we'll ensure that we return a safe value of
1237
+ // zero in the case we end up overflowing in any way.
1238
+
1239
+ SetZero ( ) ;
1240
+ return ;
1241
+ }
1242
+
1153
1243
_blocks [ index ] = ( uint ) ( carry ) ;
1154
- _length += 1 ;
1244
+ _length = length + 1 ;
1155
1245
}
1156
1246
}
1157
1247
@@ -1214,11 +1304,29 @@ public void ShiftLeft(uint shift)
1214
1304
int readIndex = ( length - 1 ) ;
1215
1305
int writeIndex = readIndex + ( int ) ( blocksToShift ) ;
1216
1306
1307
+ uint remainingBitsInLastBlock = ( uint ) BitOperations . LeadingZeroCount ( _blocks [ readIndex ] ) ;
1308
+
1309
+ if ( remainingBitsToShift > remainingBitsInLastBlock )
1310
+ {
1311
+ // We need an extra block for the partial shift
1312
+ writeIndex ++ ;
1313
+ }
1314
+
1315
+ Debug . Assert ( unchecked ( ( uint ) ( writeIndex ) ) < MaxBlockCount ) ;
1316
+
1317
+ if ( unchecked ( ( uint ) ( writeIndex ) ) >= MaxBlockCount )
1318
+ {
1319
+ // We shouldn't reach here, and the above assert will help flag this
1320
+ // during testing, but we'll ensure that we return a safe value of
1321
+ // zero in the case we end up overflowing in any way.
1322
+
1323
+ SetZero ( ) ;
1324
+ return ;
1325
+ }
1326
+
1217
1327
// Check if the shift is block aligned
1218
1328
if ( remainingBitsToShift == 0 )
1219
1329
{
1220
- Debug . Assert ( writeIndex < MaxBlockCount ) ;
1221
-
1222
1330
while ( readIndex >= 0 )
1223
1331
{
1224
1332
_blocks [ writeIndex ] = _blocks [ readIndex ] ;
@@ -1232,11 +1340,7 @@ public void ShiftLeft(uint shift)
1232
1340
Buffer . ZeroMemory ( ( byte * ) ( GetBlocksPointer ( ) ) , ( blocksToShift * sizeof ( uint ) ) ) ;
1233
1341
}
1234
1342
else
1235
- {
1236
- // We need an extra block for the partial shift
1237
- writeIndex ++ ;
1238
- Debug . Assert ( writeIndex < MaxBlockCount ) ;
1239
-
1343
+ {
1240
1344
// Set the length to hold the shifted blocks
1241
1345
_length = writeIndex + 1 ;
1242
1346
0 commit comments