Skip to content

Commit 8062156

Browse files
tannergoodingstephentoub
authored andcommitted
Fixing the float/double parsing logic to handle exponents that are too large/small (dotnet#23043)
* Fixing the float/double parsing logic to handle exponents that are too large/small * Fixing the debug assert to use >= and <= * Fixing the max exponents to be +1 to match what scale uses. Signed-off-by: dotnet-bot <anirudhagnihotry098@gmail.com>
1 parent a7a92d9 commit 8062156

File tree

2 files changed

+42
-4
lines changed

2 files changed

+42
-4
lines changed

src/Common/src/CoreLib/System/Number.NumberToFloatingPointBits.cs

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -333,6 +333,9 @@ private static ulong NumberToFloatingPointBits(ref NumberBuffer number, in Float
333333
{
334334
Debug.Assert(number.GetDigitsPointer()[0] != '0');
335335

336+
Debug.Assert(number.Scale <= FloatingPointMaxExponent);
337+
Debug.Assert(number.Scale >= FloatingPointMinExponent);
338+
336339
// The input is of the form 0.Mantissa x 10^Exponent, where 'Mantissa' are
337340
// the decimal digits of the mantissa and 'Exponent' is the decimal exponent.
338341
// We decompose the mantissa into two parts: an integer part and a fractional

src/Common/src/CoreLib/System/Number.Parsing.cs

Lines changed: 39 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,15 @@ internal partial class Number
3232
private const int Int64Precision = 19;
3333
private const int UInt64Precision = 20;
3434

35+
private const int DoubleMaxExponent = 309;
36+
private const int DoubleMinExponent = -324;
37+
38+
private const int FloatingPointMaxExponent = DoubleMaxExponent;
39+
private const int FloatingPointMinExponent = DoubleMinExponent;
40+
41+
private const int SingleMaxExponent = 39;
42+
private const int SingleMinExponent = -45;
43+
3544
/// <summary>Map from an ASCII char to its hex value, e.g. arr['b'] == 11. 0xFF means it's not a hex digit.</summary>
3645
internal static ReadOnlySpan<byte> CharToHexLookup => new byte[]
3746
{
@@ -1964,18 +1973,44 @@ private static Exception GetException(ParsingStatus status, TypeCode type)
19641973
internal static double NumberToDouble(ref NumberBuffer number)
19651974
{
19661975
number.CheckConsistency();
1976+
double result;
1977+
1978+
if (number.Scale > DoubleMaxExponent)
1979+
{
1980+
result = double.PositiveInfinity;
1981+
}
1982+
else if (number.Scale < DoubleMinExponent)
1983+
{
1984+
result = 0;
1985+
}
1986+
else
1987+
{
1988+
ulong bits = NumberToFloatingPointBits(ref number, in FloatingPointInfo.Double);
1989+
result = BitConverter.Int64BitsToDouble((long)(bits));
1990+
}
19671991

1968-
ulong bits = NumberToFloatingPointBits(ref number, in FloatingPointInfo.Double);
1969-
double result = BitConverter.Int64BitsToDouble((long)(bits));
19701992
return number.IsNegative ? -result : result;
19711993
}
19721994

19731995
internal static float NumberToSingle(ref NumberBuffer number)
19741996
{
19751997
number.CheckConsistency();
1998+
float result;
1999+
2000+
if (number.Scale > SingleMaxExponent)
2001+
{
2002+
result = float.PositiveInfinity;
2003+
}
2004+
else if (number.Scale < SingleMinExponent)
2005+
{
2006+
result = 0;
2007+
}
2008+
else
2009+
{
2010+
uint bits = (uint)(NumberToFloatingPointBits(ref number, in FloatingPointInfo.Single));
2011+
result = BitConverter.Int32BitsToSingle((int)(bits));
2012+
}
19762013

1977-
uint bits = (uint)(NumberToFloatingPointBits(ref number, in FloatingPointInfo.Single));
1978-
float result = BitConverter.Int32BitsToSingle((int)(bits));
19792014
return number.IsNegative ? -result : result;
19802015
}
19812016
}

0 commit comments

Comments
 (0)