diff --git a/src/libraries/System.Text.RegularExpressions/gen/RegexGenerator.Emitter.cs b/src/libraries/System.Text.RegularExpressions/gen/RegexGenerator.Emitter.cs index eb2ed60e3e8b0..32e79eef2745e 100644 --- a/src/libraries/System.Text.RegularExpressions/gen/RegexGenerator.Emitter.cs +++ b/src/libraries/System.Text.RegularExpressions/gen/RegexGenerator.Emitter.cs @@ -4135,8 +4135,10 @@ void EmitLoop(RegexNode node) writer.WriteLine(); // Store the loop's state - EmitStackPush(iterationMayBeEmpty ? - new[] { startingPos!, iterationCount } : + EmitStackPush( + startingPos is not null && startingStackpos is not null ? new[] { startingPos, startingStackpos, iterationCount } : + startingPos is not null ? new[] { startingPos, iterationCount } : + startingStackpos is not null ? new[] { startingStackpos, iterationCount } : new[] { iterationCount }); // Skip past the backtracking section @@ -4147,8 +4149,10 @@ void EmitLoop(RegexNode node) // Emit a backtracking section that restores the loop's state and then jumps to the previous done label string backtrack = ReserveName("LoopBacktrack"); MarkLabel(backtrack, emitSemicolon: false); - EmitStackPop(iterationMayBeEmpty ? - new[] { iterationCount, startingPos! } : + EmitStackPop( + startingPos is not null && startingStackpos is not null ? new[] { iterationCount, startingStackpos, startingPos } : + startingPos is not null ? new[] { iterationCount, startingPos } : + startingStackpos is not null ? new[] { iterationCount, startingStackpos } : new[] { iterationCount }); // We're backtracking. Check the timeout. diff --git a/src/libraries/System.Text.RegularExpressions/src/System/Text/RegularExpressions/RegexCompiler.cs b/src/libraries/System.Text.RegularExpressions/src/System/Text/RegularExpressions/RegexCompiler.cs index 1c592b9c89fb0..0b363278a5d0b 100644 --- a/src/libraries/System.Text.RegularExpressions/src/System/Text/RegularExpressions/RegexCompiler.cs +++ b/src/libraries/System.Text.RegularExpressions/src/System/Text/RegularExpressions/RegexCompiler.cs @@ -4848,11 +4848,15 @@ void EmitLoop(RegexNode node) if (analysis.IsInLoop(node)) { // Store the loop's state - EmitStackResizeIfNeeded(1 + (startingPos is not null ? 1 : 0)); + EmitStackResizeIfNeeded(1 + (startingPos is not null ? 1 : 0) + (startingStackpos is not null ? 1 : 0)); if (startingPos is not null) { EmitStackPush(() => Ldloc(startingPos)); } + if (startingStackpos is not null) + { + EmitStackPush(() => Ldloc(startingStackpos)); + } EmitStackPush(() => Ldloc(iterationCount)); // Skip past the backtracking section @@ -4868,9 +4872,15 @@ void EmitLoop(RegexNode node) EmitTimeoutCheckIfNeeded(); // iterationCount = base.runstack[--runstack]; + // startingStackpos = base.runstack[--runstack]; // startingPos = base.runstack[--runstack]; EmitStackPop(); Stloc(iterationCount); + if (startingStackpos is not null) + { + EmitStackPop(); + Stloc(startingStackpos); + } if (startingPos is not null) { EmitStackPop(); diff --git a/src/libraries/System.Text.RegularExpressions/tests/FunctionalTests/Regex.Match.Tests.cs b/src/libraries/System.Text.RegularExpressions/tests/FunctionalTests/Regex.Match.Tests.cs index f138d610e2b94..b75a249d6b555 100644 --- a/src/libraries/System.Text.RegularExpressions/tests/FunctionalTests/Regex.Match.Tests.cs +++ b/src/libraries/System.Text.RegularExpressions/tests/FunctionalTests/Regex.Match.Tests.cs @@ -392,6 +392,10 @@ public static IEnumerable Match_MemberData() yield return (@"(ver\.? |[_ ]+)?\d+(\.\d+){2,3}$", " Ver 2.0", RegexOptions.IgnoreCase, 0, 8, false, ""); yield return (@"(?:|a)?(?:\b\d){2,}", " a 0", RegexOptions.None, 0, 4, false, ""); yield return (@"(?:|a)?(\d){2,}", " a00a", RegexOptions.None, 0, 5, true, "a00"); + yield return (@"^( | )?((\w\d){3,}){3,}", " 12345678901234567", RegexOptions.None, 0, 18, false, ""); + yield return (@"^( | )?((\w\d){3,}){3,}", " 123456789012345678", RegexOptions.None, 0, 19, true, " 123456789012345678"); + yield return (@"^( | )?((\w\d){3,}){3,}", " 123456789012345678", RegexOptions.None, 0, 20, true, " 123456789012345678"); + yield return (@"^( | )?((\w\d){3,}){3,}", " 123456789012345678", RegexOptions.None, 0, 21, false, ""); // Using beginning/end of string chars \A, \Z: Actual - "\\Aaaa\\w+zzz\\Z" yield return (@"\Aaaa\w+zzz\Z", "aaaasdfajsdlfjzzz", RegexOptions.IgnoreCase, 0, 17, true, "aaaasdfajsdlfjzzz");