Index: libcxx/include/regex =================================================================== --- libcxx/include/regex +++ libcxx/include/regex @@ -3422,9 +3422,11 @@ { if (*__first == '\\') { - int __val = __traits_.value(*__temp, 10); + unsigned __val = __traits_.value(*__temp, 10); if (__val >= 1 && __val <= 9) { + if (__val > mark_count()) + __throw_regex_error(); __push_back_ref(__val); __first = ++__temp; } Index: libcxx/test/std/re/re.regex/re.regex.construct/bad_backref.pass.cpp =================================================================== --- libcxx/test/std/re/re.regex/re.regex.construct/bad_backref.pass.cpp +++ libcxx/test/std/re/re.regex/re.regex.construct/bad_backref.pass.cpp @@ -18,11 +18,11 @@ #include #include "test_macros.h" -static bool error_badbackref_thrown(const char *pat) +static bool error_badbackref_thrown(const char *pat, std::regex::flag_type f = std::regex_constants::ECMAScript) { bool result = false; try { - std::regex re(pat); + std::regex re(pat, f); } catch (const std::regex_error &ex) { result = (ex.code() == std::regex_constants::error_backref); } @@ -41,6 +41,16 @@ const char *pat1 = "a(b)c\\1234"; std::regex re(pat1, pat1 + 7); // extra chars after the end. } +// https://bugs.llvm.org/show_bug.cgi?id=34297 + assert(error_badbackref_thrown("(cat)\\1", std::regex::basic)); + assert(error_badbackref_thrown("\\(cat\\)\\1", std::regex::basic) == false); + assert(error_badbackref_thrown("(cat)\\1", std::regex::extended) == false); + assert(error_badbackref_thrown("\\(cat\\)\\1", std::regex::extended)); + assert(error_badbackref_thrown("(cat)\\1", std::regex::grep)); + assert(error_badbackref_thrown("\\(cat\\)\\1", std::regex::grep) == false); + assert(error_badbackref_thrown("(cat)\\1", std::regex::egrep) == false); + assert(error_badbackref_thrown("\\(cat\\)\\1", std::regex::egrep)); + return 0; }