Set a limit on max recursions.

Applies to last remaining recursive calls in regex creation, and format string parsing.
Added tests, and updated CI.
This commit is contained in:
jzmaddock
2024-03-16 19:06:10 +00:00
parent 237e69caf6
commit b86985e65a
9 changed files with 146 additions and 171 deletions

View File

@ -97,11 +97,11 @@ private:
void put(char_type c);
void put(const sub_match_type& sub);
void format_all();
void format_all(unsigned recursion_count = 0);
void format_perl();
void format_escape();
void format_conditional();
void format_until_scope_end();
void format_conditional(unsigned recursion_count);
void format_until_scope_end(unsigned recursion_count);
bool handle_perl_verb(bool have_brace);
inline typename Results::value_type const& get_named_sub(ForwardIter i, ForwardIter j, const std::integral_constant<bool, false>&)
@ -199,8 +199,13 @@ OutputIterator basic_regex_formatter<OutputIterator, Results, traits, ForwardIte
}
template <class OutputIterator, class Results, class traits, class ForwardIter>
void basic_regex_formatter<OutputIterator, Results, traits, ForwardIter>::format_all()
void basic_regex_formatter<OutputIterator, Results, traits, ForwardIter>::format_all(unsigned recursion_count)
{
if (recursion_count > BOOST_REGEX_MAX_RECURSION_DEPTH)
{
// We need to protect ourselves from bad format strings used as DOS attacks:
BOOST_THROW_EXCEPTION(std::runtime_error("Excessive recursion in format string, this looks like a deliberately malformed expression."));
}
// over and over:
while(m_position != m_end)
{
@ -224,7 +229,7 @@ void basic_regex_formatter<OutputIterator, Results, traits, ForwardIter>::format
++m_position;
bool have_conditional = m_have_conditional;
m_have_conditional = false;
format_until_scope_end();
format_until_scope_end(recursion_count);
m_have_conditional = have_conditional;
if(m_position == m_end)
return;
@ -255,7 +260,7 @@ void basic_regex_formatter<OutputIterator, Results, traits, ForwardIter>::format
if(m_flags & boost::regex_constants::format_all)
{
++m_position;
format_conditional();
format_conditional(recursion_count);
break;
}
put(*m_position);
@ -644,7 +649,7 @@ void basic_regex_formatter<OutputIterator, Results, traits, ForwardIter>::format
}
template <class OutputIterator, class Results, class traits, class ForwardIter>
void basic_regex_formatter<OutputIterator, Results, traits, ForwardIter>::format_conditional()
void basic_regex_formatter<OutputIterator, Results, traits, ForwardIter>::format_conditional(unsigned recursion_count)
{
if(m_position == m_end)
{
@ -692,7 +697,7 @@ void basic_regex_formatter<OutputIterator, Results, traits, ForwardIter>::format
if(m_results[v].matched)
{
m_have_conditional = true;
format_all();
format_all(++recursion_count);
m_have_conditional = false;
if((m_position != m_end) && (*m_position == static_cast<char_type>(':')))
{
@ -702,7 +707,7 @@ void basic_regex_formatter<OutputIterator, Results, traits, ForwardIter>::format
output_state saved_state = m_state;
m_state = output_none;
// format the rest of this scope:
format_until_scope_end();
format_until_scope_end(recursion_count);
// restore output state:
m_state = saved_state;
}
@ -714,7 +719,7 @@ void basic_regex_formatter<OutputIterator, Results, traits, ForwardIter>::format
m_state = output_none;
// format until ':' or ')':
m_have_conditional = true;
format_all();
format_all(++recursion_count);
m_have_conditional = false;
// restore state:
m_state = saved_state;
@ -723,17 +728,17 @@ void basic_regex_formatter<OutputIterator, Results, traits, ForwardIter>::format
// skip the ':':
++m_position;
// format the rest of this scope:
format_until_scope_end();
format_until_scope_end(recursion_count);
}
}
}
template <class OutputIterator, class Results, class traits, class ForwardIter>
void basic_regex_formatter<OutputIterator, Results, traits, ForwardIter>::format_until_scope_end()
void basic_regex_formatter<OutputIterator, Results, traits, ForwardIter>::format_until_scope_end(unsigned recursion_count)
{
do
{
format_all();
format_all(++recursion_count);
if((m_position == m_end) || (*m_position == static_cast<char_type>(')')))
return;
put(*m_position++);