From 6ec9cb08cf730156c0c4581637562056e66706bc Mon Sep 17 00:00:00 2001 From: Alexander Speshilov Date: Thu, 13 Apr 2023 19:44:47 +0300 Subject: [PATCH] Fix BigInteger parse hex strings on negative numbers fixes dotnet#74758 --- .../src/System/Numerics/BigNumber.cs | 20 +++++++------------ .../tests/BigInteger/parse.cs | 5 +++++ 2 files changed, 12 insertions(+), 13 deletions(-) diff --git a/src/libraries/System.Runtime.Numerics/src/System/Numerics/BigNumber.cs b/src/libraries/System.Runtime.Numerics/src/System/Numerics/BigNumber.cs index c31e73503dfbea..46857a9d06e786 100644 --- a/src/libraries/System.Runtime.Numerics/src/System/Numerics/BigNumber.cs +++ b/src/libraries/System.Runtime.Numerics/src/System/Numerics/BigNumber.cs @@ -466,6 +466,11 @@ private static ParsingStatus HexNumberToBigInteger(ref BigNumberBuffer number, o Debug.Assert(partialDigitCount == 0 && bitsBufferPos == -1); + if (isNegative) + { + NumericsHelpers.DangerousMakeTwosComplement(bitsBuffer); + } + // BigInteger requires leading zero blocks to be truncated. bitsBuffer = bitsBuffer.TrimEnd(0u); @@ -477,26 +482,15 @@ private static ParsingStatus HexNumberToBigInteger(ref BigNumberBuffer number, o sign = 0; bits = null; } - else if (bitsBuffer.Length == 1) + else if (bitsBuffer.Length == 1 && bitsBuffer[0] <= int.MaxValue) { - sign = (int)bitsBuffer[0]; + sign = (int)bitsBuffer[0] * (isNegative ? -1 : 1); bits = null; - - if ((!isNegative && sign < 0) || sign == int.MinValue) - { - bits = new[] { (uint)sign }; - sign = isNegative ? -1 : 1; - } } else { sign = isNegative ? -1 : 1; bits = bitsBuffer.ToArray(); - - if (isNegative) - { - NumericsHelpers.DangerousMakeTwosComplement(bits); - } } result = new BigInteger(sign, bits); diff --git a/src/libraries/System.Runtime.Numerics/tests/BigInteger/parse.cs b/src/libraries/System.Runtime.Numerics/tests/BigInteger/parse.cs index 785dc209b24e64..02d798584aad1f 100644 --- a/src/libraries/System.Runtime.Numerics/tests/BigInteger/parse.cs +++ b/src/libraries/System.Runtime.Numerics/tests/BigInteger/parse.cs @@ -132,6 +132,11 @@ public void Parse_Hex32Bits() Assert.True(BigInteger.TryParse("080000001", NumberStyles.HexNumber, null, out result)); Assert.Equal(0x80000001u, result); + // Regression test for: https://github.com/dotnet/runtime/issues/74758 + Assert.True(BigInteger.TryParse("FFFFFFFFE", NumberStyles.HexNumber, null, out result)); + Assert.Equal(new BigInteger(-2), result); + Assert.Equal(-2, result); + Assert.Throws(() => { BigInteger.Parse("zzz", NumberStyles.HexNumber);