From 78a790dfc7568622e4c7bf5832ee027eeeffb969 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Julian=20M=C3=BCller?= Date: Mon, 2 Dec 2024 21:56:16 +0100 Subject: [PATCH 1/3] ``: Repair character class escapes outside character class definitions --- stl/inc/regex | 17 ++++++++++++----- tests/std/tests/VSO_0000000_regex_use/test.cpp | 11 +++++++++++ 2 files changed, 23 insertions(+), 5 deletions(-) diff --git a/stl/inc/regex b/stl/inc/regex index f5f8e75bf46..d7804e83318 100644 --- a/stl/inc/regex +++ b/stl/inc/regex @@ -1710,7 +1710,7 @@ private: bool _OctalDigits(); void _Do_ex_class(_Meta_type); bool _CharacterClassEscape(bool); - _Prs_ret _ClassEscape(bool); + _Prs_ret _ClassEscape2(); _Prs_ret _ClassAtom(); void _ClassRanges(); void _CharacterClass(); @@ -4017,22 +4017,29 @@ bool _Parser<_FwdIt, _Elem, _RxTraits>::_CharacterClassEscape(bool _Addit) { // return false; } + const bool _Negated = _Traits.isctype(_Char, _RxTraits::_Ch_upper); if (_Addit) { _Nfa._Add_class(); + // GH-992: Outside character class definitions, _Cls completely defines the character class + // so negating _Cls and negating the entire character class is equivalent + // since the former negation is defective, do the latter instead + if (_Negated) { + _Nfa._Negate(); + } } - _Nfa._Add_named_class(_Cls, _Traits.isctype(_Char, _RxTraits::_Ch_upper)); + _Nfa._Add_named_class(_Cls, _Negated && !_Addit); _Next(); return true; } template -_Prs_ret _Parser<_FwdIt, _Elem, _RxTraits>::_ClassEscape(bool _Addit) { // check for class escape +_Prs_ret _Parser<_FwdIt, _Elem, _RxTraits>::_ClassEscape2() { // check for class escape if ((_L_flags & _L_esc_bsl) && _Char == _Esc_bsl) { // handle escape backslash if allowed _Val = _Esc_bsl; _Next(); return _Prs_chr; - } else if ((_L_flags & _L_esc_wsd) && _CharacterClassEscape(_Addit)) { + } else if ((_L_flags & _L_esc_wsd) && _CharacterClassEscape(false)) { return _Prs_set; } else if (_DecimalDigits(regex_constants::error_escape)) { // check for invalid value if (_Val != 0) { @@ -4049,7 +4056,7 @@ _Prs_ret _Parser<_FwdIt, _Elem, _RxTraits>::_ClassAtom() { // check for class at if (_Mchar == _Meta_esc) { // check for valid escape sequence _Next(); if (_L_flags & _L_grp_esc) { - return _ClassEscape(false); + return _ClassEscape2(); } else if ((_L_flags & _L_esc_ffn && _Do_ffn(_Char)) || (_L_flags & _L_esc_ffnx && _Do_ffnx(_Char))) { // advance to next character _Next(); diff --git a/tests/std/tests/VSO_0000000_regex_use/test.cpp b/tests/std/tests/VSO_0000000_regex_use/test.cpp index fcd27f0beba..34b87038623 100644 --- a/tests/std/tests/VSO_0000000_regex_use/test.cpp +++ b/tests/std/tests/VSO_0000000_regex_use/test.cpp @@ -629,6 +629,16 @@ void test_gh_5058() { } } +void test_gh_5160() { + // GH-5160 fixed mishandled negated character class escapes + // outside character class definitions + const test_wregex neg_regex(&g_regexTester, LR"(Y\S*Z)"); + neg_regex.should_search_match(L"xxxYxx\x0078xxxZxxx", L"Yxx\x0078xxxZ"); // 0078 is small Latin X + neg_regex.should_search_match(L"xxxYxx\xCF87xxxZxxx", L"Yxx\xCF87xxxZ"); // CF87 is small Greek Chi + neg_regex.should_search_fail(L"xxxYxx xxxZxxx"); + neg_regex.should_search_fail(L"xxxYxx\x2009xxxZxxx"); // 2009 is Thin Space +} + int main() { test_dev10_449367_case_insensitivity_should_work(); test_dev11_462743_regex_collate_should_not_disable_regex_icase(); @@ -657,6 +667,7 @@ int main() { test_VSO_226914_word_boundaries(); test_gh_993(); test_gh_5058(); + test_gh_5160(); return g_regexTester.result(); } From 84d631e980ba8edbbaab69765259a7ba9483032b Mon Sep 17 00:00:00 2001 From: "Stephan T. Lavavej" Date: Tue, 3 Dec 2024 08:49:11 -0800 Subject: [PATCH 2/3] Fix U+03C7 GREEK SMALL LETTER CHI and update comments. --- tests/std/tests/VSO_0000000_regex_use/test.cpp | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/tests/std/tests/VSO_0000000_regex_use/test.cpp b/tests/std/tests/VSO_0000000_regex_use/test.cpp index 34b87038623..a36ee7fdb09 100644 --- a/tests/std/tests/VSO_0000000_regex_use/test.cpp +++ b/tests/std/tests/VSO_0000000_regex_use/test.cpp @@ -633,10 +633,10 @@ void test_gh_5160() { // GH-5160 fixed mishandled negated character class escapes // outside character class definitions const test_wregex neg_regex(&g_regexTester, LR"(Y\S*Z)"); - neg_regex.should_search_match(L"xxxYxx\x0078xxxZxxx", L"Yxx\x0078xxxZ"); // 0078 is small Latin X - neg_regex.should_search_match(L"xxxYxx\xCF87xxxZxxx", L"Yxx\xCF87xxxZ"); // CF87 is small Greek Chi + neg_regex.should_search_match(L"xxxYxx\x0078xxxZxxx", L"Yxx\x0078xxxZ"); // U+0078 LATIN SMALL LETTER X + neg_regex.should_search_match(L"xxxYxx\x03C7xxxZxxx", L"Yxx\x03C7xxxZ"); // U+03C7 GREEK SMALL LETTER CHI neg_regex.should_search_fail(L"xxxYxx xxxZxxx"); - neg_regex.should_search_fail(L"xxxYxx\x2009xxxZxxx"); // 2009 is Thin Space + neg_regex.should_search_fail(L"xxxYxx\x2009xxxZxxx"); // U+2009 THIN SPACE } int main() { From b3dfac458cfcc04730dcfc0b006c68715081633f Mon Sep 17 00:00:00 2001 From: "Stephan T. Lavavej" Date: Tue, 3 Dec 2024 08:57:35 -0800 Subject: [PATCH 3/3] Comment nitpicks. --- stl/inc/regex | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/stl/inc/regex b/stl/inc/regex index d7804e83318..630349eaf89 100644 --- a/stl/inc/regex +++ b/stl/inc/regex @@ -4021,8 +4021,8 @@ bool _Parser<_FwdIt, _Elem, _RxTraits>::_CharacterClassEscape(bool _Addit) { // if (_Addit) { _Nfa._Add_class(); // GH-992: Outside character class definitions, _Cls completely defines the character class - // so negating _Cls and negating the entire character class is equivalent - // since the former negation is defective, do the latter instead + // so negating _Cls and negating the entire character class are equivalent. + // Since the former negation is defective, do the latter instead. if (_Negated) { _Nfa._Negate(); }