diff --git a/src/libraries/System.Text.RegularExpressions/src/System/Text/RegularExpressions/RegexInterpreter.cs b/src/libraries/System.Text.RegularExpressions/src/System/Text/RegularExpressions/RegexInterpreter.cs index 8d49e71e3b90aa..b5286132287297 100644 --- a/src/libraries/System.Text.RegularExpressions/src/System/Text/RegularExpressions/RegexInterpreter.cs +++ b/src/libraries/System.Text.RegularExpressions/src/System/Text/RegularExpressions/RegexInterpreter.cs @@ -129,7 +129,16 @@ private void Backtrack() { CheckTimeout(); // to ensure that any backtracking operation has a timeout check - int newpos = runtrack![runtrackpos]; + // Check if we've exhausted the backtrack stack + if (runtrackpos >= runtrack!.Length) + { + // Match failed, so we should just return with no match + runmatch!.FoundMatch = false; + SetOperator(RegexOpcode.Stop); + return; + } + + int newpos = runtrack[runtrackpos]; runtrackpos++; int back = (int)RegexOpcode.Backtracking; diff --git a/src/libraries/System.Text.RegularExpressions/tests/FunctionalTests/RegexBacktrackingTests.cs b/src/libraries/System.Text.RegularExpressions/tests/FunctionalTests/RegexBacktrackingTests.cs new file mode 100644 index 00000000000000..82304554f91c19 --- /dev/null +++ b/src/libraries/System.Text.RegularExpressions/tests/FunctionalTests/RegexBacktrackingTests.cs @@ -0,0 +1,44 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. + +using System; +using System.Collections.Generic; +using Xunit; + +namespace System.Text.RegularExpressions.Tests +{ + public class RegexBacktrackingTests + { + [Fact] + public void PossessiveQuantifierWithLazyQuantifierShouldNotThrow() + { + // This specific pattern caused IndexOutOfRangeException before the fix + var regex = new Regex(@"(?>(-*)+?-*)$"); + + // Test with input that would previously throw + Match match = regex.Match("test"); + + // Verify it doesn't throw and correctly reports no match + Assert.False(match.Success, "When backtracking stack is exhausted, match should be unsuccessful"); + } + + [Theory] + [InlineData(@"(?>(-*)+?-*)$", "test", false)] + [InlineData(@"(?>(-*)+?-*)$", "abcdef", false)] + [InlineData(@"(?>(-+)+?-*)$", "test", false)] + [InlineData(@"(?>a*)+?", "aaaaaaaa", true)] + [InlineData(@"(?>(-{50000})+?-*)$", "test", false)] // Large repeat count + [InlineData(@"((?>a+)+b)+c", "aababc", true)] // Complex nesting + public void ComplexBacktrackingShouldNotThrow(string pattern, string input, bool expectedMatch) + { + // Tests various patterns that might stress the backtracking system + var regex = new Regex(pattern); + + // Act - should not throw + Match match = regex.Match(input); + + // Verify expected match result + Assert.Equal(expectedMatch, match.Success); + } + } +} \ No newline at end of file diff --git a/src/libraries/System.Text.RegularExpressions/tests/FunctionalTests/System.Text.RegularExpressions.Tests.csproj b/src/libraries/System.Text.RegularExpressions/tests/FunctionalTests/System.Text.RegularExpressions.Tests.csproj index f57cd73cf2d26a..1c14b6f0b6184c 100644 --- a/src/libraries/System.Text.RegularExpressions/tests/FunctionalTests/System.Text.RegularExpressions.Tests.csproj +++ b/src/libraries/System.Text.RegularExpressions/tests/FunctionalTests/System.Text.RegularExpressions.Tests.csproj @@ -34,6 +34,7 @@ +