Skip to content

Commit

Permalink
Fix negative lookaround stack handling (dotnet#99424)
Browse files Browse the repository at this point in the history
* Fix negative lookaround stack handling

If the body of negative lookaround inside of a loop and containing a capture ends up successfully matching (which means the negative lookaround fails to match), it ends up erroneously leaving a position on the backtracking stack. This fix ensures that state is popped.

* Add innerloop test
  • Loading branch information
stephentoub authored Mar 12, 2024
1 parent 28978b0 commit 27214a0
Show file tree
Hide file tree
Showing 4 changed files with 16 additions and 1 deletion.
Original file line number Diff line number Diff line change
Expand Up @@ -2706,6 +2706,12 @@ void EmitNegativeLookaroundAssertion(RegexNode node)
// If the generated code ends up here, it matched the lookaround, which actually
// means failure for a _negative_ lookaround, so we need to jump to the original done.
writer.WriteLine();
if (hasCaptures && isInLoop)
{
// Pop the crawl position from the stack.
writer.WriteLine("stackpos--;");
EmitStackCookieValidate(stackCookie);
}
Goto(originalDoneLabel);
writer.WriteLine();

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2640,6 +2640,15 @@ void EmitNegativeLookaroundAssertion(RegexNode node)
// If the generated code ends up here, it matched the lookaround, which actually
// means failure for a _negative_ lookaround, so we need to jump to the original done.
// goto originalDoneLabel;
if (capturePos is not null && isInLoop)
{
// Pop the crawl position from the stack.
// stackpos--;
Ldloc(stackpos);
Ldc(1);
Sub();
Stloc(stackpos);
}
BrFar(originalDoneLabel);

// Failures (success for a negative lookaround) jump here.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -1409,7 +1409,6 @@ public static IEnumerable<object[]> RecreationalRegex_Rectangle_MemberData()
}
}

[ActiveIssue("https://github.com/dotnet/runtime/issues/98962")]
[Theory]
[MemberData(nameof(RecreationalRegex_Rectangle_MemberData))]
[OuterLoop("May take several seconds")]
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -92,6 +92,7 @@ public static IEnumerable<object[]> Match_MemberData()
yield return (@"(?:(?!(b)b)\1a)+", "babababa", RegexOptions.None, 0, 8, false, string.Empty);
yield return (@"(?:(?!(b)b)\1a)*", "babababa", RegexOptions.None, 0, 8, true, string.Empty);
yield return (@"(.*?)a(?!(a+)b\2c)\2(.*)", "baaabaac", RegexOptions.None, 0, 8, false, string.Empty);
yield return (@"(?!(abc))+\w\w\w", "abcdef", RegexOptions.None, 0, 6, true, "bcd");

// Zero-width positive lookbehind assertion
yield return (@"(\w){6}(?<=XXX)def", "abcXXXdef", RegexOptions.None, 0, 9, true, "abcXXXdef");
Expand Down

0 comments on commit 27214a0

Please sign in to comment.