mirror of
https://github.com/boostorg/regex.git
synced 2025-07-14 12:56:36 +02:00
Added throw if the number of searched states grows too large.
[SVN r15372]
This commit is contained in:
@ -26,6 +26,12 @@
|
||||
#ifndef BOOST_REGEX_MATCH_HPP
|
||||
#define BOOST_REGEX_MATCH_HPP
|
||||
|
||||
#ifndef BOOST_REGEX_MAX_STATE_COUNT
|
||||
# define BOOST_REGEX_MAX_STATE_COUNT 100000000
|
||||
#endif
|
||||
|
||||
#include <boost/limits.hpp>
|
||||
|
||||
|
||||
namespace boost{
|
||||
namespace re_detail{
|
||||
@ -175,6 +181,7 @@ class _priv_match_data
|
||||
public:
|
||||
typedef typename boost::detail::rebind_allocator<int, Allocator>::type i_alloc;
|
||||
typedef typename boost::detail::rebind_allocator<iterator, Allocator>::type it_alloc;
|
||||
typedef typename regex_iterator_traits<iterator>::difference_type difference_type;
|
||||
|
||||
match_results_base<iterator, Allocator> temp_match;
|
||||
// failure stacks:
|
||||
@ -184,9 +191,11 @@ public:
|
||||
jstack<int, Allocator> prev_acc;
|
||||
int* accumulators;
|
||||
unsigned int caccumulators;
|
||||
difference_type state_count;
|
||||
difference_type max_state_count;
|
||||
iterator* loop_starts;
|
||||
|
||||
_priv_match_data(const match_results_base<iterator, Allocator>&);
|
||||
_priv_match_data(const match_results_base<iterator, Allocator>&, iterator, iterator, unsigned);
|
||||
|
||||
~_priv_match_data()
|
||||
{
|
||||
@ -202,15 +211,32 @@ public:
|
||||
{
|
||||
return loop_starts;
|
||||
}
|
||||
void estimate_max_state_count(iterator a, iterator b, unsigned states, std::random_access_iterator_tag*)
|
||||
{
|
||||
difference_type dist = std::distance(a,b);
|
||||
if(dist > (std::numeric_limits<difference_type>::max() / (states * 3)))
|
||||
max_state_count = std::numeric_limits<difference_type>::max();
|
||||
else
|
||||
max_state_count = states * 3 * dist;
|
||||
if(max_state_count < 1000)
|
||||
max_state_count = 1000;
|
||||
}
|
||||
void estimate_max_state_count(iterator a, iterator b, unsigned states, void*)
|
||||
{
|
||||
// we don't know how long the sequence is:
|
||||
max_state_count = BOOST_REGEX_MAX_STATE_COUNT;
|
||||
}
|
||||
};
|
||||
|
||||
template <class iterator, class Allocator>
|
||||
_priv_match_data<iterator, Allocator>::_priv_match_data(const match_results_base<iterator, Allocator>& m)
|
||||
_priv_match_data<iterator, Allocator>::_priv_match_data(const match_results_base<iterator, Allocator>& m, iterator a, iterator b, unsigned states)
|
||||
: temp_match(m), matches(64, m.allocator()), prev_pos(64, m.allocator()), prev_record(64, m.allocator())
|
||||
{
|
||||
accumulators = 0;
|
||||
caccumulators = 0;
|
||||
loop_starts = 0;
|
||||
state_count = 0;
|
||||
estimate_max_state_count(a, b, states, static_cast<regex_iterator_traits<iterator>::iterator_category*>(0));
|
||||
}
|
||||
|
||||
template <class iterator, class Allocator>
|
||||
@ -297,6 +323,7 @@ bool query_match_aux(iterator first,
|
||||
typedef typename traits::size_type traits_size_type;
|
||||
typedef typename traits::uchar_type traits_uchar_type;
|
||||
typedef typename is_byte<charT>::width_type width_type;
|
||||
typedef typename re_detail::regex_iterator_traits<iterator>::difference_type difference_type;
|
||||
|
||||
// declare some local aliases to reduce pointer loads
|
||||
// good optimising compilers should make this unnecessary!!
|
||||
@ -306,6 +333,7 @@ bool query_match_aux(iterator first,
|
||||
jstack<int, Allocator>& prev_acc = pd.prev_acc;
|
||||
match_results_base<iterator, Allocator>& temp_match = pd.temp_match;
|
||||
temp_match.set_first(first);
|
||||
difference_type& state_count = pd.state_count;
|
||||
|
||||
const re_syntax_base* ptr = access::first(e);
|
||||
bool match_found = false;
|
||||
@ -337,6 +365,7 @@ bool query_match_aux(iterator first,
|
||||
while(first != last)
|
||||
{
|
||||
jm_assert(ptr);
|
||||
++state_count;
|
||||
switch(ptr->type)
|
||||
{
|
||||
case syntax_element_match:
|
||||
@ -816,6 +845,7 @@ bool query_match_aux(iterator first,
|
||||
while(true)
|
||||
{
|
||||
jm_assert(ptr);
|
||||
++state_count;
|
||||
switch(ptr->type)
|
||||
{
|
||||
case syntax_element_match:
|
||||
@ -929,6 +959,14 @@ bool query_match_aux(iterator first,
|
||||
|
||||
failure:
|
||||
|
||||
//
|
||||
// check to see if we've been searching too many states:
|
||||
//
|
||||
if(state_count >= pd.max_state_count)
|
||||
{
|
||||
throw std::runtime_error("Max regex search depth exceeded.");
|
||||
}
|
||||
|
||||
//
|
||||
// check for possible partial match:
|
||||
//
|
||||
@ -1177,7 +1215,7 @@ unsigned int reg_grep2(Predicate foo, I first, I last, const reg_expression<char
|
||||
|
||||
flags |= match_init;
|
||||
|
||||
_priv_match_data<I, A2> pd(m);
|
||||
_priv_match_data<I, A2> pd(m, first, last, e.size());
|
||||
|
||||
const unsigned char* _map = access::get_map(e);
|
||||
unsigned int type;
|
||||
@ -1648,7 +1686,7 @@ bool regex_match(iterator first, iterator last, match_results<iterator, Allocato
|
||||
m.set_line(1, first);
|
||||
}
|
||||
flags |= match_all; // must match all of input.
|
||||
re_detail::_priv_match_data<iterator, Allocator> pd(m);
|
||||
re_detail::_priv_match_data<iterator, Allocator> pd(m, first, last, e.size());
|
||||
iterator restart;
|
||||
bool result = re_detail::query_match_aux(first, last, m, e, flags, pd, &restart);
|
||||
return result;
|
||||
|
Reference in New Issue
Block a user