de-fuzz: prevent infinite recursion in recursive expressions (case 14).

This commit is contained in:
jzmaddock
2017-02-15 19:44:41 +00:00
parent b05fafe1c5
commit edd94320c7
4 changed files with 44 additions and 0 deletions

View File

@ -348,6 +348,7 @@ struct recursion_info
const re_syntax_base* preturn_address;
Results results;
repeater_count<iterator>* repeater_stack;
iterator location_of_start;
};
#ifdef BOOST_MSVC

View File

@ -953,6 +953,19 @@ bool perl_matcher<BidiIterator, Allocator, traits>::match_recursion()
{
BOOST_ASSERT(pstate->type == syntax_element_recurse);
//
// See if we've seen this recursion before at this location, if we have then
// we need to prevent infinite recursion:
//
for(std::vector<recursion_info<results_type> >::const_reverse_iterator i = recursion_stack.rbegin(); i != recursion_stack.rend(); ++i)
{
if(i->idx == static_cast<const re_brace*>(static_cast<const re_jump*>(pstate)->alt.p)->index)
{
if(i->location_of_start == position)
return false;
break;
}
}
//
// Backup call stack:
//
push_recursion_pop();
@ -968,6 +981,7 @@ bool perl_matcher<BidiIterator, Allocator, traits>::match_recursion()
recursion_stack.back().results = *m_presult;
pstate = static_cast<const re_jump*>(pstate)->alt.p;
recursion_stack.back().idx = static_cast<const re_brace*>(pstate)->index;
recursion_stack.back().location_of_start = position;
//if(static_cast<const re_recurse*>(pstate)->state_id > 0)
{
push_repeater_count(-(2 + static_cast<const re_brace*>(pstate)->index), &next_count);

View File

@ -900,10 +900,27 @@ bool perl_matcher<BidiIterator, Allocator, traits>::match_recursion()
{
recursion_stack.reserve(50);
}
//
// See if we've seen this recursion before at this location, if we have then
// we need to prevent infinite recursion:
//
for(std::vector<recursion_info<results_type> >::const_reverse_iterator i = recursion_stack.rbegin(); i != recursion_stack.rend(); ++i)
{
if(i->idx == static_cast<const re_brace*>(static_cast<const re_jump*>(pstate)->alt.p)->index)
{
if(i->location_of_start == position)
return false;
break;
}
}
//
// Now get on with it:
//
recursion_stack.push_back(recursion_info<results_type>());
recursion_stack.back().preturn_address = pstate->next.p;
recursion_stack.back().results = *m_presult;
recursion_stack.back().repeater_stack = next_count;
recursion_stack.back().location_of_start = position;
pstate = static_cast<const re_jump*>(pstate)->alt.p;
recursion_stack.back().idx = static_cast<const re_brace*>(pstate)->index;