From 3870c0f8dcc78e21a10075fd75a56c9a9c3aff1a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Julian=20M=C3=BCller?= Date: Sat, 1 Nov 2025 19:39:58 +0100 Subject: [PATCH 1/2] ``: Fix matching of loops with context-dependent empty matches and bounded number of repetitions --- stl/inc/regex | 10 +++++++--- tests/std/tests/VSO_0000000_regex_use/test.cpp | 8 ++++++++ 2 files changed, 15 insertions(+), 3 deletions(-) diff --git a/stl/inc/regex b/stl/inc/regex index 2409ce9bd5..f6cb5ee5fd 100644 --- a/stl/inc/regex +++ b/stl/inc/regex @@ -4096,11 +4096,15 @@ bool _Matcher3<_BidIt, _Elem, _RxTraits, _It, _Alloc>::_Match_pat(_Node_base* _N _Frame._Loop_idx_sav = _Sav._Loop_idx; _Frame._Loop_frame_idx_sav = _Sav._Loop_frame_idx; _Sav._Loop_frame_idx = _Frame_idx; - if (_Progress) { - ++_Sav._Loop_idx; - } else { // try only one more match after an empty match + + // optimization: try only one more match after an empty match + // if there is no maximum number of reps + if (!_Progress && _Nr->_Max < 0) { _Sav._Loop_idx = _Nr->_Min; + } else { + ++_Sav._Loop_idx; } + _STD fill(_Tgt_state._Grp_valid.begin() + static_cast(_Sav._Group_first), _Tgt_state._Grp_valid.end(), false); _Next = _Nr->_Next; diff --git a/tests/std/tests/VSO_0000000_regex_use/test.cpp b/tests/std/tests/VSO_0000000_regex_use/test.cpp index 794e3ffd06..2d9b61ee17 100644 --- a/tests/std/tests/VSO_0000000_regex_use/test.cpp +++ b/tests/std/tests/VSO_0000000_regex_use/test.cpp @@ -2263,6 +2263,13 @@ void test_gh_5792() { g_regexTester.should_match("bc", "(?:(?!ab))+bc"); } +void test_gh_5797() { + // : Loops with bounded number of repetitions and context-dependent empty alternative are mishandled + g_regexTester.should_match("bc", "(?:b|c|(?=bc)){3}"); + g_regexTester.should_match("bc", "(^|b|c){3}"); + g_regexTester.should_match("bc", "(^|b|c){3}", regex_constants::extended); +} + void test_gh_5798() { // GH-5798: : Process generic loops non-recursively. // This extends our test coverage on non-simple loops, @@ -2401,6 +2408,7 @@ int main() { test_gh_5774(); test_gh_5790(); test_gh_5792(); + test_gh_5797(); test_gh_5798(); return g_regexTester.result(); From 6957a9b312c6f46f09daf29a489dba3413f706ae Mon Sep 17 00:00:00 2001 From: "Stephan T. Lavavej" Date: Mon, 3 Nov 2025 06:23:47 -0800 Subject: [PATCH 2/2] Cite bug number in comment. --- tests/std/tests/VSO_0000000_regex_use/test.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/std/tests/VSO_0000000_regex_use/test.cpp b/tests/std/tests/VSO_0000000_regex_use/test.cpp index 2d9b61ee17..8a491d03ad 100644 --- a/tests/std/tests/VSO_0000000_regex_use/test.cpp +++ b/tests/std/tests/VSO_0000000_regex_use/test.cpp @@ -2264,7 +2264,7 @@ void test_gh_5792() { } void test_gh_5797() { - // : Loops with bounded number of repetitions and context-dependent empty alternative are mishandled + // GH-5797: : Loops with bounded number of repetitions and context-dependent empty alternative are mishandled g_regexTester.should_match("bc", "(?:b|c|(?=bc)){3}"); g_regexTester.should_match("bc", "(^|b|c){3}"); g_regexTester.should_match("bc", "(^|b|c){3}", regex_constants::extended);