[libc++] Validate the entire regex is consumed
This change would have warned about the bug found in D62451.
No unit tests since the exception should never throw.
Differential Revision: https://reviews.llvm.org/D62452
diff --git a/libcxx/include/regex b/libcxx/include/regex
index d13f9ad..d6f5585 100644
--- a/libcxx/include/regex
+++ b/libcxx/include/regex
@@ -965,7 +965,8 @@
error_stack,
__re_err_grammar,
__re_err_empty,
- __re_err_unknown
+ __re_err_unknown,
+ __re_err_parse
};
} // regex_constants
@@ -2539,8 +2540,7 @@
: __flags_(__f), __marked_count_(0), __loop_count_(0), __open_count_(0),
__end_(0)
{
- if (__get_grammar(__flags_) == 0) __flags_ |= regex_constants::ECMAScript;
- __parse(__p, __p + __traits_.length(__p));
+ __init(__p, __p + __traits_.length(__p));
}
_LIBCPP_INLINE_VISIBILITY
@@ -2548,8 +2548,7 @@
: __flags_(__f), __marked_count_(0), __loop_count_(0), __open_count_(0),
__end_(0)
{
- if (__get_grammar(__flags_) == 0) __flags_ |= regex_constants::ECMAScript;
- __parse(__p, __p + __len);
+ __init(__p, __p + __len);
}
// basic_regex(const basic_regex&) = default;
@@ -2561,8 +2560,7 @@
: __flags_(__f), __marked_count_(0), __loop_count_(0), __open_count_(0),
__end_(0)
{
- if (__get_grammar(__flags_) == 0) __flags_ |= regex_constants::ECMAScript;
- __parse(__p.begin(), __p.end());
+ __init(__p.begin(), __p.end());
}
template <class _ForwardIterator>
@@ -2572,8 +2570,7 @@
: __flags_(__f), __marked_count_(0), __loop_count_(0), __open_count_(0),
__end_(0)
{
- if (__get_grammar(__flags_) == 0) __flags_ |= regex_constants::ECMAScript;
- __parse(__first, __last);
+ __init(__first, __last);
}
#ifndef _LIBCPP_CXX03_LANG
_LIBCPP_INLINE_VISIBILITY
@@ -2582,8 +2579,7 @@
: __flags_(__f), __marked_count_(0), __loop_count_(0), __open_count_(0),
__end_(0)
{
- if (__get_grammar(__flags_) == 0) __flags_ |= regex_constants::ECMAScript;
- __parse(__il.begin(), __il.end());
+ __init(__il.begin(), __il.end());
}
#endif // _LIBCPP_CXX03_LANG
@@ -2699,6 +2695,9 @@
unsigned __loop_count() const {return __loop_count_;}
template <class _ForwardIterator>
+ void
+ __init(_ForwardIterator __first, _ForwardIterator __last);
+ template <class _ForwardIterator>
_ForwardIterator
__parse(_ForwardIterator __first, _ForwardIterator __last);
template <class _ForwardIterator>
@@ -3056,6 +3055,17 @@
template <class _CharT, class _Traits>
template <class _ForwardIterator>
+void
+basic_regex<_CharT, _Traits>::__init(_ForwardIterator __first, _ForwardIterator __last)
+{
+ if (__get_grammar(__flags_) == 0) __flags_ |= regex_constants::ECMAScript;
+ _ForwardIterator __temp = __parse(__first, __last);
+ if ( __temp != __last)
+ __throw_regex_error<regex_constants::__re_err_parse>();
+}
+
+template <class _CharT, class _Traits>
+template <class _ForwardIterator>
_ForwardIterator
basic_regex<_CharT, _Traits>::__parse(_ForwardIterator __first,
_ForwardIterator __last)
diff --git a/libcxx/src/regex.cpp b/libcxx/src/regex.cpp
index a971f64..d31e494 100644
--- a/libcxx/src/regex.cpp
+++ b/libcxx/src/regex.cpp
@@ -53,6 +53,8 @@
return "An invalid regex grammar has been requested.";
case regex_constants::__re_err_empty:
return "An empty regex is not allowed in the POSIX grammar.";
+ case regex_constants::__re_err_parse:
+ return "The parser did not consume the entire regular expression.";
default:
break;
}