Index: include/regex =================================================================== --- include/regex +++ include/regex @@ -3442,23 +3442,32 @@ { if (__first != __last) { - _ForwardIterator __temp = _VSTD::next(__first); - if (__temp != __last) + if (*__first == '\\') { - if (*__first == '\\') + _ForwardIterator __temp = _VSTD::next(__first); + if (__temp == __last) + __throw_regex_error(); + + switch (*__temp) { - switch (*__temp) - { - case '^': - case '.': - case '*': - case '[': - case '$': - case '\\': - __push_char(*__temp); - __first = ++__temp; + case '^': + case '.': + case '*': + case '[': + case '$': + case '\\': + __push_char(*__temp); + __first = ++__temp; + break; + case '(': + case ')': + case '{': + case '}': + break; + default: + if (*__temp >= '1' && *__temp <= '9') break; - } + __throw_regex_error(); } } } @@ -3473,34 +3482,36 @@ { if (__first != __last) { - _ForwardIterator __temp = _VSTD::next(__first); - if (__temp != __last) + if (*__first == '\\') { - if (*__first == '\\') + _ForwardIterator __temp = _VSTD::next(__first); + if (__temp == __last) + __throw_regex_error(); + + switch (*__temp) { - switch (*__temp) - { - case '^': - case '.': - case '*': - case '[': - case '$': - case '\\': - case '(': - case ')': - case '|': - case '+': - case '?': - case '{': - case '}': - __push_char(*__temp); - __first = ++__temp; - break; - default: - if ((__flags_ & 0x1F0) == awk) - __first = __parse_awk_escape(++__first, __last); + case '^': + case '.': + case '*': + case '[': + case '$': + case '\\': + case '(': + case ')': + case '|': + case '+': + case '?': + case '{': + case '}': + __push_char(*__temp); + __first = ++__temp; + break; + default: + if ((__flags_ & 0x1F0) == awk) { + __first = __parse_awk_escape(++__first, __last); break; } + __throw_regex_error(); } } } Index: test/std/re/re.regex/re.regex.construct/bad_escape.pass.cpp =================================================================== --- test/std/re/re.regex/re.regex.construct/bad_escape.pass.cpp +++ test/std/re/re.regex/re.regex.construct/bad_escape.pass.cpp @@ -19,11 +19,13 @@ #include #include "test_macros.h" -static bool error_escape_thrown(const char *pat) +static bool error_escape_thrown(const char *pat, + std::regex_constants::syntax_option_type + syntax = std::regex_constants::ECMAScript) { bool result = false; try { - std::regex re(pat); + std::regex re(pat, syntax); } catch (const std::regex_error &ex) { result = (ex.code() == std::regex_constants::error_escape); } @@ -45,4 +47,58 @@ assert(!error_escape_thrown("[\\cA]")); assert(!error_escape_thrown("\\cA")); + const std::regex_constants::syntax_option_type basic = + std::regex_constants::basic; + + assert(error_escape_thrown("\\a", basic)); + assert(error_escape_thrown("\\n", basic)); + assert(error_escape_thrown("\\t", basic)); + assert(error_escape_thrown("\\0", basic)); + assert(error_escape_thrown("\\/", basic)); + assert(error_escape_thrown("\\\n", basic)); + assert(error_escape_thrown("\\", basic)); + + assert(!error_escape_thrown("[\\a]", basic)); + assert(!error_escape_thrown("\\(a\\)", basic)); + assert(!error_escape_thrown("\\(ab\\)\\1", basic)); + assert(!error_escape_thrown("a\\{1,2\\}", basic)); + assert(!error_escape_thrown("\\.", basic)); + assert(!error_escape_thrown("\\*", basic)); + + const std::regex_constants::syntax_option_type extended = + std::regex_constants::extended; + + assert(error_escape_thrown("\\a", extended)); + assert(error_escape_thrown("\\n", extended)); + assert(error_escape_thrown("\\t", extended)); + assert(error_escape_thrown("\\0", extended)); + assert(error_escape_thrown("(ab)\\1", extended)); + assert(error_escape_thrown("\\/", extended)); + assert(error_escape_thrown("\\\n", extended)); + assert(error_escape_thrown("\\", extended)); + + assert(!error_escape_thrown("[\\a]", extended)); + assert(!error_escape_thrown("\\(a\\)", extended)); + assert(!error_escape_thrown("\\{\\}", extended)); + assert(!error_escape_thrown("\\.", extended)); + assert(!error_escape_thrown("\\*", extended)); + + const std::regex_constants::syntax_option_type awk = + std::regex_constants::awk; + + assert(error_escape_thrown("\\z", awk)); + assert(error_escape_thrown("[\\z]", awk)); + assert(error_escape_thrown("\\9", awk)); + assert(error_escape_thrown("\\\n", awk)); + assert(error_escape_thrown("\\", awk)); + + assert(!error_escape_thrown("\\n", awk)); + assert(!error_escape_thrown("\\t", awk)); + assert(!error_escape_thrown("\\/", awk)); + assert(!error_escape_thrown("\\(a\\)", awk)); + assert(!error_escape_thrown("\\{\\}", awk)); + assert(!error_escape_thrown("\\0", awk)); + assert(!error_escape_thrown("\\1", awk)); + assert(!error_escape_thrown("\\.", awk)); + assert(!error_escape_thrown("\\*", awk)); }