From a6fe12b60cc2ce686736e67801866a20091e4f94 Mon Sep 17 00:00:00 2001 From: Hamid Reza Arzaghi Date: Sun, 29 Nov 2020 00:34:09 +0330 Subject: [PATCH 1/5] Fix the issue --- stl/inc/regex | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/stl/inc/regex b/stl/inc/regex index 2cfb6d8de33..f3a8286ccb4 100644 --- a/stl/inc/regex +++ b/stl/inc/regex @@ -3683,6 +3683,10 @@ _BidIt _Matcher<_BidIt, _Elem, _RxTraits, _It>::_Skip(_BidIt _First_arg, _BidIt _It _Next = _First_arg; ++_Next; + if (_Sflags & regex_constants::icase) { + _Ch = static_cast(_Traits.translate_nocase(static_cast<_Elem>(_Ch))); + } + if (_Node->_Coll && _Lookup_coll(_First_arg, _Next, _Node->_Coll) != _First_arg) { _Found = true; } else if (_Node->_Ranges From 393becbdb70076d2f8d04e7af4f49fbf21f65bf3 Mon Sep 17 00:00:00 2001 From: Hamid Reza Arzaghi Date: Sun, 29 Nov 2020 03:40:12 +0330 Subject: [PATCH 2/5] Add test cases --- tests/std/include/test_regex_support.hpp | 61 +++++++++++++++++++ .../std/tests/VSO_0000000_regex_use/test.cpp | 29 +++++++++ 2 files changed, 90 insertions(+) diff --git a/tests/std/include/test_regex_support.hpp b/tests/std/include/test_regex_support.hpp index c4a5802c831..23662e85a95 100644 --- a/tests/std/include/test_regex_support.hpp +++ b/tests/std/include/test_regex_support.hpp @@ -240,3 +240,64 @@ class test_regex { } } }; + +class test_wregex { + regex_fixture* const fixture; + const std::wstring pattern; + const std::regex_constants::syntax_option_type syntax; + const std::wregex r; + +public: + test_wregex(regex_fixture* fixture, const std::wstring& pattern, + std::regex_constants::syntax_option_type syntax = std::regex_constants::ECMAScript) + : fixture(fixture), pattern(pattern), syntax(syntax), r(pattern, syntax) {} + + test_wregex(const test_wregex&) = delete; + test_wregex& operator=(const test_wregex&) = delete; + + void should_search_match(const std::wstring& subject, const std::wstring& expected, + const std::regex_constants::match_flag_type match_flags = std::regex_constants::match_default) const { + std::wsmatch mr; + try { + const bool search_result = std::regex_search(subject, mr, r, match_flags); + if (!search_result || mr[0] != expected) { + wprintf(LR"(Expected regex_search("%s", regex("%s", 0x%X), 0x%X) to find "%s", )", subject.c_str(), + pattern.c_str(), static_cast(syntax), static_cast(match_flags), + expected.c_str()); + if (search_result) { + wprintf(LR"(but it matched "%s")" + "\n", + mr.str().c_str()); + } else { + puts("but it failed to match"); + } + + fixture->fail_regex(); + } + } catch (const std::regex_error& e) { + wprintf(LR"(Failed to regex_search("%s", regex("%s", 0x%X), 0x%X): regex_error: )", subject.c_str(), + pattern.c_str(), static_cast(syntax), static_cast(match_flags)); + printf("%s\n", e.what()); + fixture->fail_regex(); + } + } + + void should_search_fail(const std::wstring& subject, + const std::regex_constants::match_flag_type match_flags = std::regex_constants::match_default) const { + std::wsmatch mr; + try { + if (std::regex_search(subject, mr, r, match_flags)) { + wprintf(LR"(Expected regex_search("%s", regex("%s", 0x%X), 0x%X) to not match, but it found "%s")" + "\n", + subject.c_str(), pattern.c_str(), static_cast(syntax), + static_cast(match_flags), mr.str().c_str()); + fixture->fail_regex(); + } + } catch (const std::regex_error& e) { + wprintf(LR"(Failed to regex_search("%s", regex("%s", 0x%X), 0x%X): regex_error: )", subject.c_str(), + pattern.c_str(), static_cast(syntax), static_cast(match_flags)); + printf("%s\n", e.what()); + fixture->fail_regex(); + } + } +}; diff --git a/tests/std/tests/VSO_0000000_regex_use/test.cpp b/tests/std/tests/VSO_0000000_regex_use/test.cpp index 29e993dc431..6e25762ce9f 100644 --- a/tests/std/tests/VSO_0000000_regex_use/test.cpp +++ b/tests/std/tests/VSO_0000000_regex_use/test.cpp @@ -546,6 +546,34 @@ void test_VSO_226914_word_boundaries() { aWordAny.should_search_fail("aa", match_not_bow | match_not_eow); } +void test_GH_993_regex_character_class_case_insensitive_search() { + { + const wstring subject = L" Copyright"; + const test_wregex case_regex(&g_regexTester, LR"([a-z][a-z])", ECMAScript); + const test_wregex icase_regex(&g_regexTester, LR"([a-z][a-z])", ECMAScript | icase); + + case_regex.should_search_match(subject, L"op"); + icase_regex.should_search_match(subject, L"Co"); + } + + { + const wstring subject = L"blahZblah"; + const test_wregex Z_case_regex(&g_regexTester, LR"([Z])", ECMAScript); + const test_wregex Z_icase_regex(&g_regexTester, LR"([Z])", ECMAScript | icase); + const test_wregex z_case_regex(&g_regexTester, LR"([z])", ECMAScript); + const test_wregex z_icase_regex(&g_regexTester, LR"([z])", ECMAScript | icase); + + Z_case_regex.should_search_match(subject, L"Z"); + Z_icase_regex.should_search_match(subject, L"Z"); + z_icase_regex.should_search_match(subject, L"Z"); + + z_case_regex.should_search_fail(subject); + z_case_regex.should_search_fail(subject, match_not_bow); + z_case_regex.should_search_fail(subject, match_not_eow); + z_case_regex.should_search_fail(subject, match_not_bow | match_not_eow); + } +} + int main() { test_dev10_449367_case_insensitivity_should_work(); test_dev11_462743_regex_collate_should_not_disable_regex_icase(); @@ -572,6 +600,7 @@ int main() { test_VSO_225160_match_bol_flag(); test_VSO_225160_match_eol_flag(); test_VSO_226914_word_boundaries(); + test_GH_993_regex_character_class_case_insensitive_search(); return g_regexTester.result(); } From 631a26f9a22830f13f1f31adeb57a22c5ad4f15a Mon Sep 17 00:00:00 2001 From: "Stephan T. Lavavej" Date: Wed, 2 Dec 2020 04:27:25 -0800 Subject: [PATCH 3/5] Add test case. --- tests/std/tests/VSO_0000000_regex_use/test.cpp | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/tests/std/tests/VSO_0000000_regex_use/test.cpp b/tests/std/tests/VSO_0000000_regex_use/test.cpp index 6e25762ce9f..fe202ca392a 100644 --- a/tests/std/tests/VSO_0000000_regex_use/test.cpp +++ b/tests/std/tests/VSO_0000000_regex_use/test.cpp @@ -571,6 +571,12 @@ void test_GH_993_regex_character_class_case_insensitive_search() { z_case_regex.should_search_fail(subject, match_not_bow); z_case_regex.should_search_fail(subject, match_not_eow); z_case_regex.should_search_fail(subject, match_not_bow | match_not_eow); + + const wstring lowercase_subject = L"hungry_zombies"; + Z_case_regex.should_search_fail(lowercase_subject); + Z_icase_regex.should_search_match(lowercase_subject, L"z"); + z_case_regex.should_search_match(lowercase_subject, L"z"); + z_icase_regex.should_search_match(lowercase_subject, L"z"); } } From 075b6e5ffac835acffdb49297daf988b474cd8b5 Mon Sep 17 00:00:00 2001 From: "Stephan T. Lavavej" Date: Wed, 2 Dec 2020 04:27:46 -0800 Subject: [PATCH 4/5] Add quotes around e.what(). --- tests/std/include/test_regex_support.hpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/tests/std/include/test_regex_support.hpp b/tests/std/include/test_regex_support.hpp index 23662e85a95..5d9531d6f39 100644 --- a/tests/std/include/test_regex_support.hpp +++ b/tests/std/include/test_regex_support.hpp @@ -277,7 +277,7 @@ class test_wregex { } catch (const std::regex_error& e) { wprintf(LR"(Failed to regex_search("%s", regex("%s", 0x%X), 0x%X): regex_error: )", subject.c_str(), pattern.c_str(), static_cast(syntax), static_cast(match_flags)); - printf("%s\n", e.what()); + printf("\"%s\"\n", e.what()); fixture->fail_regex(); } } @@ -296,7 +296,7 @@ class test_wregex { } catch (const std::regex_error& e) { wprintf(LR"(Failed to regex_search("%s", regex("%s", 0x%X), 0x%X): regex_error: )", subject.c_str(), pattern.c_str(), static_cast(syntax), static_cast(match_flags)); - printf("%s\n", e.what()); + printf("\"%s\"\n", e.what()); fixture->fail_regex(); } } From c7098b983a95a561f2741f8c285a7a16fffcbdb7 Mon Sep 17 00:00:00 2001 From: "Stephan T. Lavavej" Date: Mon, 14 Dec 2020 20:56:48 -0800 Subject: [PATCH 5/5] Extract _Uelem. --- stl/inc/regex | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/stl/inc/regex b/stl/inc/regex index f3a8286ccb4..194b60f8ace 100644 --- a/stl/inc/regex +++ b/stl/inc/regex @@ -3677,21 +3677,22 @@ _BidIt _Matcher<_BidIt, _Elem, _RxTraits, _It>::_Skip(_BidIt _First_arg, _BidIt case _N_class: { // check for string match for (; _First_arg != _Last; ++_First_arg) { // look for starting match + using _Uelem = typename _RxTraits::_Uelem; bool _Found; - auto _Ch = static_cast(*_First_arg); + auto _Ch = static_cast<_Uelem>(*_First_arg); _Node_class<_Elem, _RxTraits>* _Node = static_cast<_Node_class<_Elem, _RxTraits>*>(_Nx); _It _Next = _First_arg; ++_Next; if (_Sflags & regex_constants::icase) { - _Ch = static_cast(_Traits.translate_nocase(static_cast<_Elem>(_Ch))); + _Ch = static_cast<_Uelem>(_Traits.translate_nocase(static_cast<_Elem>(_Ch))); } if (_Node->_Coll && _Lookup_coll(_First_arg, _Next, _Node->_Coll) != _First_arg) { _Found = true; } else if (_Node->_Ranges && (_Lookup_range( - static_cast(_Sflags & regex_constants::collate + static_cast<_Uelem>(_Sflags & regex_constants::collate ? _Traits.translate(static_cast<_Elem>(_Ch)) : static_cast<_Elem>(_Ch)), _Node->_Ranges))) {