Skip to content

Commit ee88b5f

Browse files
CopilotEgorBo
andauthored
Fix TryParsePartial under-reporting charsConsumed with leading whitespace
Co-authored-by: EgorBo <523221+EgorBo@users.noreply.github.com>
1 parent 209fdfd commit ee88b5f

3 files changed

Lines changed: 20 additions & 4 deletions

File tree

src/libraries/System.Private.CoreLib/src/System/Number.Parsing.cs

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -380,13 +380,14 @@ internal static ParsingStatus TryParseBinaryIntegerStyle<TChar, TInteger>(ReadOn
380380
}
381381
else
382382
{
383-
value = value.Slice(index);
384-
index = 0;
383+
// Slice a copy rather than reassigning value, so that index (and thus the number
384+
// of elements reported as consumed) stays relative to the original input.
385+
ReadOnlySpan<TChar> remaining = value.Slice(index);
385386

386387
ReadOnlySpan<TChar> positiveSign = info.PositiveSignTChar<TChar>();
387388
ReadOnlySpan<TChar> negativeSign = info.NegativeSignTChar<TChar>();
388389

389-
if (!positiveSign.IsEmpty && value.StartsWith(positiveSign))
390+
if (!positiveSign.IsEmpty && remaining.StartsWith(positiveSign))
390391
{
391392
index += positiveSign.Length;
392393

@@ -396,7 +397,7 @@ internal static ParsingStatus TryParseBinaryIntegerStyle<TChar, TInteger>(ReadOn
396397
}
397398
num = TChar.CastToUInt32(value[index]);
398399
}
399-
else if (!negativeSign.IsEmpty && value.StartsWith(negativeSign))
400+
else if (!negativeSign.IsEmpty && remaining.StartsWith(negativeSign))
400401
{
401402
isNegative = true;
402403
index += negativeSign.Length;

src/libraries/System.Runtime/tests/System.Runtime.Tests/System/Int32Tests.cs

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1056,6 +1056,15 @@ public static IEnumerable<object[]> TryParsePartial_TestData()
10561056

10571057
// Stop at null character
10581058
yield return new object[] { "123\0abc", NumberStyles.Integer, null, 123, 4 };
1059+
1060+
// Leading whitespace is counted as consumed even when the signs aren't the invariant "+"/"-"
1061+
NumberFormatInfo nonInvariantSignFormat = new NumberFormatInfo() { NegativeSign = "\u2212" };
1062+
yield return new object[] { " 5", NumberStyles.Integer, nonInvariantSignFormat, 5, 2 };
1063+
yield return new object[] { " 123abc", NumberStyles.Integer, nonInvariantSignFormat, 123, 5 };
1064+
yield return new object[] { " +123abc", NumberStyles.Integer, nonInvariantSignFormat, 123, 6 };
1065+
yield return new object[] { " \u2212456xyz", NumberStyles.Integer, nonInvariantSignFormat, -456, 6 };
1066+
yield return new object[] { " \u2212456", NumberStyles.Integer, nonInvariantSignFormat, -456, 6 };
1067+
yield return new object[] { " 123 abc", NumberStyles.Integer, nonInvariantSignFormat, 123, 7 };
10591068
}
10601069

10611070
[Theory]

src/libraries/System.Runtime/tests/System.Runtime.Tests/System/UInt32Tests.cs

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -481,6 +481,12 @@ public static IEnumerable<object[]> TryParsePartial_TestData()
481481

482482
// Valid number without trailing characters
483483
yield return new object[] { "123", NumberStyles.Integer, null, 123u, 3 };
484+
485+
// Leading whitespace is counted as consumed even when the signs aren't the invariant "+"/"-"
486+
NumberFormatInfo nonInvariantSignFormat = new NumberFormatInfo() { NegativeSign = "\u2212" };
487+
yield return new object[] { " 5", NumberStyles.Integer, nonInvariantSignFormat, 5u, 2 };
488+
yield return new object[] { " 123abc", NumberStyles.Integer, nonInvariantSignFormat, 123u, 5 };
489+
yield return new object[] { " +123abc", NumberStyles.Integer, nonInvariantSignFormat, 123u, 6 };
484490
}
485491

486492
[Theory]

0 commit comments

Comments
 (0)