Skip to content

Commit b864585

Browse files
authored
Fix integer overflow in string.IndexOf range validation (#128191)
1 parent ea32e27 commit b864585

2 files changed

Lines changed: 34 additions & 4 deletions

File tree

src/libraries/System.Private.CoreLib/src/System/String.Searching.cs

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -132,7 +132,7 @@ private int IndexOfCharOrdinalIgnoreCase(char value, int startIndex, int count)
132132
ArgumentOutOfRangeException.ThrowIfNegative(startIndex);
133133
ArgumentOutOfRangeException.ThrowIfGreaterThan(startIndex, Length);
134134
ArgumentOutOfRangeException.ThrowIfNegative(count);
135-
ArgumentOutOfRangeException.ThrowIfGreaterThan(startIndex + count, Length);
135+
ArgumentOutOfRangeException.ThrowIfGreaterThan(count, Length - startIndex);
136136

137137
int subIndex;
138138

@@ -432,9 +432,10 @@ public int IndexOf(Rune value, int startIndex, StringComparison comparisonType)
432432
/// </returns>
433433
public unsafe int IndexOf(Rune value, int startIndex, int count, StringComparison comparisonType)
434434
{
435-
ArgumentOutOfRangeException.ThrowIfLessThan(startIndex, 0);
436-
ArgumentOutOfRangeException.ThrowIfLessThan(count, 0);
437-
ArgumentOutOfRangeException.ThrowIfGreaterThan(startIndex + count, Length);
435+
ArgumentOutOfRangeException.ThrowIfNegative(startIndex);
436+
ArgumentOutOfRangeException.ThrowIfGreaterThan(startIndex, Length);
437+
ArgumentOutOfRangeException.ThrowIfNegative(count);
438+
ArgumentOutOfRangeException.ThrowIfGreaterThan(count, Length - startIndex);
438439

439440
// Convert value to span
440441
ReadOnlySpan<char> valueChars = value.AsSpan(stackalloc char[Rune.MaxUtf16CharsPerRune]);

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

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1346,6 +1346,35 @@ public static void ImplicitCast_NullString_ReturnsDefaultSpan()
13461346
Assert.True(span == default);
13471347
}
13481348

1349+
[Fact]
1350+
public static void IndexOf_Char_OrdinalIgnoreCase_ThrowsArgumentOutOfRangeException()
1351+
{
1352+
AssertExtensions.Throws<ArgumentOutOfRangeException>("startIndex", () => "Hello".IndexOf('o', -1, 0, StringComparison.OrdinalIgnoreCase));
1353+
AssertExtensions.Throws<ArgumentOutOfRangeException>("startIndex", () => "Hello".IndexOf('o', 6, 0, StringComparison.OrdinalIgnoreCase));
1354+
AssertExtensions.Throws<ArgumentOutOfRangeException>("count", () => "Hello".IndexOf('o', 0, -1, StringComparison.OrdinalIgnoreCase));
1355+
AssertExtensions.Throws<ArgumentOutOfRangeException>("count", () => "Hello".IndexOf('o', 0, 6, StringComparison.OrdinalIgnoreCase));
1356+
AssertExtensions.Throws<ArgumentOutOfRangeException>("count", () => "Hello".IndexOf('o', 3, 3, StringComparison.OrdinalIgnoreCase));
1357+
AssertExtensions.Throws<ArgumentOutOfRangeException>("count", () => "Hello".IndexOf('o', 1, int.MaxValue, StringComparison.OrdinalIgnoreCase));
1358+
}
1359+
1360+
[Fact]
1361+
public static void IndexOf_Rune_StartIndexCount_ThrowsArgumentOutOfRangeException()
1362+
{
1363+
AssertExtensions.Throws<ArgumentOutOfRangeException>("startIndex", () => "Hello".IndexOf(new Rune('o'), -1, 0));
1364+
AssertExtensions.Throws<ArgumentOutOfRangeException>("startIndex", () => "Hello".IndexOf(new Rune('o'), 6, 0));
1365+
AssertExtensions.Throws<ArgumentOutOfRangeException>("count", () => "Hello".IndexOf(new Rune('o'), 0, -1));
1366+
AssertExtensions.Throws<ArgumentOutOfRangeException>("count", () => "Hello".IndexOf(new Rune('o'), 0, 6));
1367+
AssertExtensions.Throws<ArgumentOutOfRangeException>("count", () => "Hello".IndexOf(new Rune('o'), 3, 3));
1368+
AssertExtensions.Throws<ArgumentOutOfRangeException>("count", () => "Hello".IndexOf(new Rune('o'), 1, int.MaxValue));
1369+
1370+
AssertExtensions.Throws<ArgumentOutOfRangeException>("startIndex", () => "Hello".IndexOf(new Rune('o'), -1, 0, StringComparison.OrdinalIgnoreCase));
1371+
AssertExtensions.Throws<ArgumentOutOfRangeException>("startIndex", () => "Hello".IndexOf(new Rune('o'), 6, 0, StringComparison.OrdinalIgnoreCase));
1372+
AssertExtensions.Throws<ArgumentOutOfRangeException>("count", () => "Hello".IndexOf(new Rune('o'), 0, -1, StringComparison.OrdinalIgnoreCase));
1373+
AssertExtensions.Throws<ArgumentOutOfRangeException>("count", () => "Hello".IndexOf(new Rune('o'), 0, 6, StringComparison.OrdinalIgnoreCase));
1374+
AssertExtensions.Throws<ArgumentOutOfRangeException>("count", () => "Hello".IndexOf(new Rune('o'), 3, 3, StringComparison.OrdinalIgnoreCase));
1375+
AssertExtensions.Throws<ArgumentOutOfRangeException>("count", () => "Hello".IndexOf(new Rune('o'), 1, int.MaxValue, StringComparison.OrdinalIgnoreCase));
1376+
}
1377+
13491378
public static IEnumerable<object[]> IndexOf_SingleLetter_StringComparison_TestData()
13501379
{
13511380
yield return new object[] { "Hello", 'l', 0, int.MaxValue, StringComparison.Ordinal, null, 2 };

0 commit comments

Comments
 (0)