diff options
Diffstat (limited to 'include/regex')
| -rw-r--r-- | include/regex | 138 |
1 files changed, 86 insertions, 52 deletions
diff --git a/include/regex b/include/regex index 77ca648109b2..ff84b2738b78 100644 --- a/include/regex +++ b/include/regex @@ -773,6 +773,8 @@ _LIBCPP_PUSH_MACROS #include <__undef_macros> +#define _LIBCPP_REGEX_COMPLEXITY_FACTOR 4096 + _LIBCPP_BEGIN_NAMESPACE_STD namespace regex_constants @@ -2407,17 +2409,28 @@ __bracket_expression<_CharT, _Traits>::__exec(__state& __s) const goto __exit; } } - if (!__neg_chars_.empty()) + // set of "__found" chars = + // union(complement(union(__neg_chars_, __neg_mask_)), + // other cases...) + // + // __neg_chars_ and __neg_mask_'d better be handled together, as there + // are no short circuit opportunities. + // + // In addition, when __neg_mask_/__neg_chars_ is empty, they should be + // treated as all ones/all chars. { - for (size_t __i = 0; __i < __neg_chars_.size(); ++__i) - { - if (__ch == __neg_chars_[__i]) - goto __is_neg_char; - } + const bool __in_neg_mask = (__neg_mask_ == 0) || + __traits_.isctype(__ch, __neg_mask_); + const bool __in_neg_chars = + __neg_chars_.empty() || + std::find(__neg_chars_.begin(), __neg_chars_.end(), __ch) != + __neg_chars_.end(); + if (!(__in_neg_mask || __in_neg_chars)) + { __found = true; goto __exit; + } } -__is_neg_char: if (!__ranges_.empty()) { string_type __s2 = __collate_ ? @@ -2449,11 +2462,6 @@ __is_neg_char: __found = true; goto __exit; } - if (__neg_mask_ && !__traits_.isctype(__ch, __neg_mask_)) - { - __found = true; - goto __exit; - } } else __found = __negate_; // force reject @@ -4056,6 +4064,8 @@ basic_regex<_CharT, _Traits>::__parse_DUP_COUNT(_ForwardIterator __first, __first != __last && ( __val = __traits_.value(*__first, 10)) != -1; ++__first) { + if (__c >= std::numeric_limits<int>::max() / 10) + __throw_regex_error<regex_constants::error_badbrace>(); __c *= 10; __c += __val; } @@ -4317,8 +4327,12 @@ basic_regex<_CharT, _Traits>::__parse_decimal_escape(_ForwardIterator __first, unsigned __v = *__first - '0'; for (++__first; __first != __last && '0' <= *__first && *__first <= '9'; ++__first) + { + if (__v >= std::numeric_limits<unsigned>::max() / 10) + __throw_regex_error<regex_constants::error_backref>(); __v = 10 * __v + *__first - '0'; - if (__v > mark_count()) + } + if (__v == 0 || __v > mark_count()) __throw_regex_error<regex_constants::error_backref>(); __push_back_ref(__v); } @@ -5226,11 +5240,11 @@ public: // size: _LIBCPP_INLINE_VISIBILITY - size_type size() const {return __matches_.size();} - _LIBCPP_INLINE_VISIBILITY - size_type max_size() const {return __matches_.max_size();} + size_type size() const _NOEXCEPT {return __matches_.size();} _LIBCPP_INLINE_VISIBILITY - bool empty() const {return size() == 0;} + size_type max_size() const _NOEXCEPT {return __matches_.max_size();} + _LIBCPP_NODISCARD_AFTER_CXX17 _LIBCPP_INLINE_VISIBILITY + bool empty() const _NOEXCEPT {return size() == 0;} // element access: _LIBCPP_INLINE_VISIBILITY @@ -5263,15 +5277,15 @@ public: // format: template <class _OutputIter> _OutputIter - format(_OutputIter __output, const char_type* __fmt_first, + format(_OutputIter __output_iter, const char_type* __fmt_first, const char_type* __fmt_last, regex_constants::match_flag_type __flags = regex_constants::format_default) const; template <class _OutputIter, class _ST, class _SA> _LIBCPP_INLINE_VISIBILITY _OutputIter - format(_OutputIter __output, const basic_string<char_type, _ST, _SA>& __fmt, + format(_OutputIter __output_iter, const basic_string<char_type, _ST, _SA>& __fmt, regex_constants::match_flag_type __flags = regex_constants::format_default) const - {return format(__output, __fmt.data(), __fmt.data() + __fmt.size(), __flags);} + {return format(__output_iter, __fmt.data(), __fmt.data() + __fmt.size(), __flags);} template <class _ST, class _SA> _LIBCPP_INLINE_VISIBILITY basic_string<char_type, _ST, _SA> @@ -5383,7 +5397,7 @@ match_results<_BidirectionalIterator, _Allocator>::__init(unsigned __s, template <class _BidirectionalIterator, class _Allocator> template <class _OutputIter> _OutputIter -match_results<_BidirectionalIterator, _Allocator>::format(_OutputIter __output, +match_results<_BidirectionalIterator, _Allocator>::format(_OutputIter __output_iter, const char_type* __fmt_first, const char_type* __fmt_last, regex_constants::match_flag_type __flags) const { @@ -5392,27 +5406,27 @@ match_results<_BidirectionalIterator, _Allocator>::format(_OutputIter __output, for (; __fmt_first != __fmt_last; ++__fmt_first) { if (*__fmt_first == '&') - __output = _VSTD::copy(__matches_[0].first, __matches_[0].second, - __output); + __output_iter = _VSTD::copy(__matches_[0].first, __matches_[0].second, + __output_iter); else if (*__fmt_first == '\\' && __fmt_first + 1 != __fmt_last) { ++__fmt_first; if ('0' <= *__fmt_first && *__fmt_first <= '9') { size_t __i = *__fmt_first - '0'; - __output = _VSTD::copy((*this)[__i].first, - (*this)[__i].second, __output); + __output_iter = _VSTD::copy((*this)[__i].first, + (*this)[__i].second, __output_iter); } else { - *__output = *__fmt_first; - ++__output; + *__output_iter = *__fmt_first; + ++__output_iter; } } else { - *__output = *__fmt_first; - ++__output; + *__output_iter = *__fmt_first; + ++__output_iter; } } } @@ -5425,52 +5439,54 @@ match_results<_BidirectionalIterator, _Allocator>::format(_OutputIter __output, switch (__fmt_first[1]) { case '$': - *__output = *++__fmt_first; - ++__output; + *__output_iter = *++__fmt_first; + ++__output_iter; break; case '&': ++__fmt_first; - __output = _VSTD::copy(__matches_[0].first, __matches_[0].second, - __output); + __output_iter = _VSTD::copy(__matches_[0].first, __matches_[0].second, + __output_iter); break; case '`': ++__fmt_first; - __output = _VSTD::copy(__prefix_.first, __prefix_.second, __output); + __output_iter = _VSTD::copy(__prefix_.first, __prefix_.second, __output_iter); break; case '\'': ++__fmt_first; - __output = _VSTD::copy(__suffix_.first, __suffix_.second, __output); + __output_iter = _VSTD::copy(__suffix_.first, __suffix_.second, __output_iter); break; default: if ('0' <= __fmt_first[1] && __fmt_first[1] <= '9') { ++__fmt_first; - size_t __i = *__fmt_first - '0'; + size_t __idx = *__fmt_first - '0'; if (__fmt_first + 1 != __fmt_last && '0' <= __fmt_first[1] && __fmt_first[1] <= '9') { ++__fmt_first; - __i = 10 * __i + *__fmt_first - '0'; + if (__idx >= std::numeric_limits<size_t>::max() / 10) + __throw_regex_error<regex_constants::error_escape>(); + __idx = 10 * __idx + *__fmt_first - '0'; } - __output = _VSTD::copy((*this)[__i].first, - (*this)[__i].second, __output); + __output_iter = _VSTD::copy((*this)[__idx].first, + (*this)[__idx].second, __output_iter); } else { - *__output = *__fmt_first; - ++__output; + *__output_iter = *__fmt_first; + ++__output_iter; } break; } } else { - *__output = *__fmt_first; - ++__output; + *__output_iter = *__fmt_first; + ++__output_iter; } } } - return __output; + return __output_iter; } template <class _BidirectionalIterator, class _Allocator> @@ -5552,8 +5568,14 @@ basic_regex<_CharT, _Traits>::__match_at_start_ecma( __states.back().__node_ = __st; __states.back().__flags_ = __flags; __states.back().__at_first_ = __at_first; + int __counter = 0; + int __length = __last - __first; do { + ++__counter; + if (__counter % _LIBCPP_REGEX_COMPLEXITY_FACTOR == 0 && + __counter / _LIBCPP_REGEX_COMPLEXITY_FACTOR >= __length) + __throw_regex_error<regex_constants::error_complexity>(); __state& __s = __states.back(); if (__s.__node_) __s.__node_->__exec(__s); @@ -5627,8 +5649,14 @@ basic_regex<_CharT, _Traits>::__match_at_start_posix_nosubs( __states.back().__flags_ = __flags; __states.back().__at_first_ = __at_first; bool __matched = false; + int __counter = 0; + int __length = __last - __first; do { + ++__counter; + if (__counter % _LIBCPP_REGEX_COMPLEXITY_FACTOR == 0 && + __counter / _LIBCPP_REGEX_COMPLEXITY_FACTOR >= __length) + __throw_regex_error<regex_constants::error_complexity>(); __state& __s = __states.back(); if (__s.__node_) __s.__node_->__exec(__s); @@ -5724,8 +5752,14 @@ basic_regex<_CharT, _Traits>::__match_at_start_posix_subs( __states.back().__at_first_ = __at_first; const _CharT* __current = __first; bool __matched = false; + int __counter = 0; + int __length = __last - __first; do { + ++__counter; + if (__counter % _LIBCPP_REGEX_COMPLEXITY_FACTOR == 0 && + __counter / _LIBCPP_REGEX_COMPLEXITY_FACTOR >= __length) + __throw_regex_error<regex_constants::error_complexity>(); __state& __s = __states.back(); if (__s.__node_) __s.__node_->__exec(__s); @@ -6460,7 +6494,7 @@ typedef regex_token_iterator<wstring::const_iterator> wsregex_token_iterator; template <class _OutputIterator, class _BidirectionalIterator, class _Traits, class _CharT> _OutputIterator -regex_replace(_OutputIterator __output, +regex_replace(_OutputIterator __output_iter, _BidirectionalIterator __first, _BidirectionalIterator __last, const basic_regex<_CharT, _Traits>& __e, const _CharT* __fmt, regex_constants::match_flag_type __flags = regex_constants::match_default) @@ -6471,7 +6505,7 @@ regex_replace(_OutputIterator __output, if (__i == __eof) { if (!(__flags & regex_constants::format_no_copy)) - __output = _VSTD::copy(__first, __last, __output); + __output_iter = _VSTD::copy(__first, __last, __output_iter); } else { @@ -6479,29 +6513,29 @@ regex_replace(_OutputIterator __output, for (size_t __len = char_traits<_CharT>::length(__fmt); __i != __eof; ++__i) { if (!(__flags & regex_constants::format_no_copy)) - __output = _VSTD::copy(__i->prefix().first, __i->prefix().second, __output); - __output = __i->format(__output, __fmt, __fmt + __len, __flags); + __output_iter = _VSTD::copy(__i->prefix().first, __i->prefix().second, __output_iter); + __output_iter = __i->format(__output_iter, __fmt, __fmt + __len, __flags); __lm = __i->suffix(); if (__flags & regex_constants::format_first_only) break; } if (!(__flags & regex_constants::format_no_copy)) - __output = _VSTD::copy(__lm.first, __lm.second, __output); + __output_iter = _VSTD::copy(__lm.first, __lm.second, __output_iter); } - return __output; + return __output_iter; } template <class _OutputIterator, class _BidirectionalIterator, class _Traits, class _CharT, class _ST, class _SA> inline _LIBCPP_INLINE_VISIBILITY _OutputIterator -regex_replace(_OutputIterator __output, +regex_replace(_OutputIterator __output_iter, _BidirectionalIterator __first, _BidirectionalIterator __last, const basic_regex<_CharT, _Traits>& __e, const basic_string<_CharT, _ST, _SA>& __fmt, regex_constants::match_flag_type __flags = regex_constants::match_default) { - return _VSTD::regex_replace(__output, __first, __last, __e, __fmt.c_str(), __flags); + return _VSTD::regex_replace(__output_iter, __first, __last, __e, __fmt.c_str(), __flags); } template <class _Traits, class _CharT, class _ST, class _SA, class _FST, |
