diff --git a/stl/inc/regex b/stl/inc/regex index a5795f344df..07835e51318 100644 --- a/stl/inc/regex +++ b/stl/inc/regex @@ -3641,9 +3641,13 @@ bool _Matcher<_BidIt, _Elem, _RxTraits, _It>::_Match_pat(_Node_base* _Nx) { // c { // record current position _Node_capture* _Node = static_cast<_Node_capture*>(_Nx); _Tgt_state._Grps[_Node->_Idx]._Begin = _Tgt_state._Cur; - // CodeQL [SM02323] Comparing unchanging unsigned int _Node->_Idx to decreasing size_t _Idx is safe. - for (size_t _Idx = _Tgt_state._Grp_valid.size(); _Node->_Idx < _Idx;) { - _Tgt_state._Grp_valid[--_Idx] = false; + if (!(_Sflags + & (regex_constants::basic | regex_constants::extended | regex_constants::grep + | regex_constants::egrep | regex_constants::awk))) { + // CodeQL [SM02323] Comparing unchanging unsigned int _Node->_Idx to decreasing size_t _Idx is safe. + for (size_t _Idx = _Tgt_state._Grp_valid.size(); _Node->_Idx < _Idx;) { + _Tgt_state._Grp_valid[--_Idx] = false; + } } break; diff --git a/tests/std/tests/VSO_0000000_regex_use/test.cpp b/tests/std/tests/VSO_0000000_regex_use/test.cpp index 4aa304947ff..79c0822ac3d 100644 --- a/tests/std/tests/VSO_0000000_regex_use/test.cpp +++ b/tests/std/tests/VSO_0000000_regex_use/test.cpp @@ -1457,6 +1457,47 @@ void test_gh_5374() { g_regexTester.should_match("bc", R"((a*)b\1c)", ECMAScript); } +void test_gh_5377() { + // GH-5377 : Do not reset matched capture groups in POSIX regexes + for (syntax_option_type option : {extended, awk, egrep}) { + test_regex abcd_regex(&g_regexTester, R"(^((a)|(b)|(c)|(d))+$)", option); + abcd_regex.should_search_match_capture_groups( + "abcd", "abcd", match_default, {{3, 4}, {0, 1}, {1, 2}, {2, 3}, {3, 4}}); + abcd_regex.should_search_match_capture_groups( + "acbd", "acbd", match_default, {{3, 4}, {0, 1}, {2, 3}, {1, 2}, {3, 4}}); + abcd_regex.should_search_match_capture_groups( + "dcba", "dcba", match_default, {{3, 4}, {3, 4}, {2, 3}, {1, 2}, {0, 1}}); + } + + for (syntax_option_type option : {basic, grep}) { + test_regex abcd_regex(&g_regexTester, R"(^\(\(a\)*\(b\)*\(c\)*\(d\)*\)*$)", option); + abcd_regex.should_search_match_capture_groups( + "abcd", "abcd", match_default, {{0, 4}, {0, 1}, {1, 2}, {2, 3}, {3, 4}}); + abcd_regex.should_search_match_capture_groups( + "acbd", "acbd", match_default, {{2, 4}, {0, 1}, {2, 3}, {1, 2}, {3, 4}}); + abcd_regex.should_search_match_capture_groups( + "dcba", "dcba", match_default, {{3, 4}, {3, 4}, {2, 3}, {1, 2}, {0, 1}}); + + test_regex backref_regex(&g_regexTester, R"(^\(\(a\)\{0,1\}\(\2b\)\{0,1\}\)*)", option); + backref_regex.should_search_match_capture_groups("aaababb", "aaabab", match_default, {{4, 6}, {1, 2}, {4, 6}}); + } + + { + // ECMAScript's behavior is different: + test_regex abcd_regex(&g_regexTester, R"(^((a)|(b)|(c)|(d))+$)", ECMAScript); + abcd_regex.should_search_match_capture_groups( + "abcd", "abcd", match_default, {{3, 4}, {-1, -1}, {-1, -1}, {-1, -1}, {3, 4}}); + abcd_regex.should_search_match_capture_groups( + "acbd", "acbd", match_default, {{3, 4}, {-1, -1}, {-1, -1}, {-1, -1}, {3, 4}}); + abcd_regex.should_search_match_capture_groups( + "dcba", "dcba", match_default, {{3, 4}, {3, 4}, {-1, -1}, {-1, -1}, {-1, -1}}); + + test_regex backref_regex(&g_regexTester, R"(^((a){0,1}(\2b){0,1})*)", ECMAScript); + backref_regex.should_search_match_capture_groups( + "aaababb", "aaababb", match_default, {{6, 7}, {-1, -1}, {6, 7}}); + } +} + int main() { test_dev10_449367_case_insensitivity_should_work(); test_dev11_462743_regex_collate_should_not_disable_regex_icase(); @@ -1499,6 +1540,7 @@ int main() { test_gh_5364(); test_gh_5371(); test_gh_5374(); + test_gh_5377(); return g_regexTester.result(); }