From 4b7715fbdd3b0580b6df4d72ef69ab45610c03cc Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Wed, 22 Oct 2025 19:30:48 +0000 Subject: [PATCH 1/2] Initial plan From f623d24ed2021b599f5ee410ac88aa638172cb5c Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Wed, 22 Oct 2025 20:12:02 +0000 Subject: [PATCH 2/2] Add regression tests for lookbehind captures Co-authored-by: stephentoub <2642209+stephentoub@users.noreply.github.com> --- .../FunctionalTests/Regex.Match.Tests.cs | 55 +++++++++++++++++++ 1 file changed, 55 insertions(+) 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 9a0463aa27a402..4121e095301ee6 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 @@ -1892,6 +1892,61 @@ public static IEnumerable Match_Advanced_TestData() } }; } + + // Lookbehind assertions with captures - regression test for https://github.com/dotnet/runtime/issues/117605 + // Verify that captures in positive lookbehind assertions are preserved correctly in compiled mode + if (!RegexHelpers.IsNonBacktracking(engine)) + { + yield return new object[] + { + engine, + @"(?<=(abc)+?123)a", "abcabc123a", RegexOptions.None, 0, 10, + new CaptureData[] + { + new CaptureData("a", 9, 1), + new CaptureData("abc", 3, 3, new CaptureData[] { new CaptureData("abc", 3, 3) }) + } + }; + + yield return new object[] + { + engine, + @"(?<=(abc){2,}?123)a", "abcabc123a", RegexOptions.None, 0, 10, + new CaptureData[] + { + new CaptureData("a", 9, 1), + new CaptureData("abc", 0, 3, new CaptureData[] + { + new CaptureData("abc", 3, 3), + new CaptureData("abc", 0, 3) + }) + } + }; + + yield return new object[] + { + engine, + @"(?<=(abc)+?)a", "abca", RegexOptions.None, 0, 4, + new CaptureData[] + { + new CaptureData("a", 3, 1), + new CaptureData("abc", 0, 3, new CaptureData[] { new CaptureData("abc", 0, 3) }) + } + }; + + // Multiple groups in lookbehind + yield return new object[] + { + engine, + @"(?<=(?'1'abc)+?(?'2')123)a", "abcabc123a", RegexOptions.None, 0, 10, + new CaptureData[] + { + new CaptureData("a", 9, 1), + new CaptureData("abc", 3, 3, new CaptureData[] { new CaptureData("abc", 3, 3) }), + new CaptureData(string.Empty, 6, 0, new CaptureData[] { new CaptureData(string.Empty, 6, 0) }) + } + }; + } } }