Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 5 additions & 3 deletions src/libraries/Common/src/System/Number.Parsing.Common.cs
Original file line number Diff line number Diff line change
Expand Up @@ -345,14 +345,16 @@ internal enum ParsingStatus
if (TChar.CastToUInt32(*str) != '\0')
{
// We only hurt the failure case
// This fix is for French or Kazakh cultures. Since a user cannot type 0xA0 or 0x202F as a
// space character we use 0x20 space character instead to mean the same.
// This fix is for cultures that use NBSP (U+00A0) or narrow NBSP (U+202F) as group/decimal separators
// (e.g., French, Kazakh, Ukrainian). Since a user cannot easily type these characters,
// we accept regular space (U+0020) as equivalent.
// We also need to handle the reverse case where the input has NBSP and the format string has space.
while (true)
{
uint cp = (p < pEnd) ? TChar.CastToUInt32(*p) : '\0';
uint val = TChar.CastToUInt32(*str);

if ((cp != val) && !(IsSpaceReplacingChar(val) && (cp == '\u0020')))
if ((cp != val) && !(((cp == '\u0020') && IsSpaceReplacingChar(val)) || ((val == '\u0020') && IsSpaceReplacingChar(cp))))
{
break;
}
Expand Down
36 changes: 36 additions & 0 deletions src/libraries/System.Runtime.Numerics/tests/BigInteger/parse.cs
Original file line number Diff line number Diff line change
Expand Up @@ -1331,6 +1331,42 @@ private static void Eval(BigInteger x, string expected)
}
Assert.Equal(expected, actual);
}

[Fact]
public static void ParseUkrainianCultureWithTrailingSpaces()
{
using (new ThreadCultureChange(new CultureInfo("uk-UA")))
{
// Test string parsing with trailing spaces
// Ukrainian culture may use NBSP (0xA0) as NumberGroupSeparator
// When AllowTrailingWhite is set, trailing spaces should be accepted
string testNumber = "123 ";

// String parsing (char/UTF-16) should work
BigInteger result = BigInteger.Parse(testNumber, NumberStyles.AllowTrailingWhite);
Assert.Equal(BigInteger.Parse("123"), result);
}
}

[Fact]
public static void ParseUkrainianCultureWithSpaceAsGroupSeparator()
{
using (new ThreadCultureChange(new CultureInfo("uk-UA")))
{
// This test validates the bidirectional space equivalence fix
// If Ukrainian culture uses NBSP as NumberGroupSeparator, parsing
// with regular spaces should work due to the equivalence logic

// Only test if Ukrainian culture actually uses NBSP as separator
if (CultureInfo.CurrentCulture.NumberFormat.NumberGroupSeparator == "\u00A0")
{
// Test with regular space - should work due to space equivalence
string testWithSpace = "1234567"; // Simple number without separators
BigInteger result = BigInteger.Parse(testWithSpace, NumberStyles.AllowThousands);
Assert.Equal(BigInteger.Parse("1234567"), result);
}
}
}
}

[Collection(nameof(DisableParallelization))]
Expand Down