Skip to content

Commit 0ad5249

Browse files
authored
Fix decimal NumberStyles validation (#126644)
Fixes #126643 Also fixes bug in `decimal` similar to #123289
1 parent 0fc6976 commit 0ad5249

4 files changed

Lines changed: 43 additions & 5 deletions

File tree

src/libraries/System.Private.CoreLib/src/Resources/Strings.resx

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4480,4 +4480,7 @@
44804480
<data name="Argument_FunctionPointersInvalid">
44814481
<value>Function pointer types are not valid.</value>
44824482
</data>
4483+
<data name="Arg_HexBinaryStylesNotSupported" xml:space="preserve">
4484+
<value>The number styles AllowHexSpecifier and AllowBinarySpecifier are not supported on the decimal type.</value>
4485+
</data>
44834486
</root>

src/libraries/System.Private.CoreLib/src/System/Decimal.cs

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -534,7 +534,7 @@ public static decimal Parse(string s, NumberStyles style, IFormatProvider? provi
534534

535535
public static decimal Parse(ReadOnlySpan<char> s, NumberStyles style = NumberStyles.Number, IFormatProvider? provider = null)
536536
{
537-
NumberFormatInfo.ValidateParseStyleFloatingPoint(style);
537+
NumberFormatInfo.ValidateParseStyleDecimal(style);
538538
return Number.ParseDecimal(s, style, NumberFormatInfo.GetInstance(provider));
539539
}
540540

@@ -550,7 +550,7 @@ public static decimal Parse(ReadOnlySpan<char> s, NumberStyles style = NumberSty
550550

551551
public static bool TryParse([NotNullWhen(true)] string? s, NumberStyles style, IFormatProvider? provider, out decimal result)
552552
{
553-
NumberFormatInfo.ValidateParseStyleFloatingPoint(style);
553+
NumberFormatInfo.ValidateParseStyleDecimal(style);
554554

555555
if (s == null)
556556
{
@@ -562,7 +562,7 @@ public static bool TryParse([NotNullWhen(true)] string? s, NumberStyles style, I
562562

563563
public static bool TryParse(ReadOnlySpan<char> s, NumberStyles style, IFormatProvider? provider, out decimal result)
564564
{
565-
NumberFormatInfo.ValidateParseStyleFloatingPoint(style);
565+
NumberFormatInfo.ValidateParseStyleDecimal(style);
566566
return Number.TryParseDecimal(s, style, NumberFormatInfo.GetInstance(provider), out result) == Number.ParsingStatus.OK;
567567
}
568568

@@ -1834,14 +1834,14 @@ private static bool TryConvertTo<TOther>(decimal value, [MaybeNullWhen(false)] o
18341834
/// <inheritdoc cref="INumberBase{TSelf}.Parse(ReadOnlySpan{byte}, NumberStyles, IFormatProvider?)" />
18351835
public static decimal Parse(ReadOnlySpan<byte> utf8Text, NumberStyles style = NumberStyles.Number, IFormatProvider? provider = null)
18361836
{
1837-
NumberFormatInfo.ValidateParseStyleInteger(style);
1837+
NumberFormatInfo.ValidateParseStyleDecimal(style);
18381838
return Number.ParseDecimal(utf8Text, style, NumberFormatInfo.GetInstance(provider));
18391839
}
18401840

18411841
/// <inheritdoc cref="INumberBase{TSelf}.TryParse(ReadOnlySpan{byte}, NumberStyles, IFormatProvider?, out TSelf)" />
18421842
public static bool TryParse(ReadOnlySpan<byte> utf8Text, NumberStyles style, IFormatProvider? provider, out decimal result)
18431843
{
1844-
NumberFormatInfo.ValidateParseStyleInteger(style);
1844+
NumberFormatInfo.ValidateParseStyleDecimal(style);
18451845
return Number.TryParseDecimal(utf8Text, style, NumberFormatInfo.GetInstance(provider), out result) == Number.ParsingStatus.OK;
18461846
}
18471847

src/libraries/System.Private.CoreLib/src/System/Globalization/NumberFormatInfo.cs

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -846,5 +846,17 @@ static void ThrowInvalid(NumberStyles value)
846846
}
847847
}
848848
}
849+
850+
internal static void ValidateParseStyleDecimal(NumberStyles style)
851+
{
852+
// Check for undefined flags or hex/binary specifiers.
853+
if ((style & (InvalidNumberStyles | NumberStyles.AllowHexSpecifier | NumberStyles.AllowBinarySpecifier)) != 0)
854+
{
855+
ThrowInvalid(style);
856+
857+
static void ThrowInvalid(NumberStyles value) =>
858+
throw new ArgumentException((value & InvalidNumberStyles) != 0 ? SR.Argument_InvalidNumberStyles : SR.Arg_HexBinaryStylesNotSupported, nameof(style));
859+
}
860+
}
849861
}
850862
}

src/libraries/System.Runtime/tests/System.Globalization.Tests/NumberFormatInfo/NumberFormatInfoValidateParseStyle.cs

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -45,5 +45,28 @@ public void ValidateParseStyle_Float(NumberStyles style, bool valid)
4545
float.Parse(value, style); // Should not throw
4646
}
4747
}
48+
49+
[Theory]
50+
[InlineData(unchecked((NumberStyles)0xFFFFFC00), false)]
51+
[InlineData(NumberStyles.HexNumber | NumberStyles.Integer, false)]
52+
[InlineData(NumberStyles.AllowHexSpecifier, false)]
53+
[InlineData(NumberStyles.HexFloat, false)]
54+
[InlineData(NumberStyles.Float, true)]
55+
[InlineData(NumberStyles.AllowBinarySpecifier, false)]
56+
[InlineData(NumberStyles.AllowHexSpecifier | NumberStyles.AllowExponent, false)]
57+
[InlineData(NumberStyles.None, true)]
58+
public void ValidateParseStyle_Decimal(NumberStyles style, bool valid)
59+
{
60+
if (!valid)
61+
{
62+
AssertExtensions.Throws<ArgumentException>("style", () => decimal.Parse("0", style));
63+
AssertExtensions.Throws<ArgumentException>("style", () => decimal.Parse("0"u8, style));
64+
}
65+
else
66+
{
67+
decimal.Parse("0", style); // Should not throw
68+
decimal.Parse("0"u8, style); // Should not throw
69+
}
70+
}
4871
}
4972
}

0 commit comments

Comments
 (0)