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; const re_syntax_base* preturn_address;
Results results; Results results;
repeater_count<iterator>* repeater_stack; repeater_count<iterator>* repeater_stack;
iterator location_of_start;
}; };
#ifdef BOOST_MSVC #ifdef BOOST_MSVC

View File

@ -953,6 +953,19 @@ bool perl_matcher<BidiIterator, Allocator, traits>::match_recursion()
{ {
BOOST_ASSERT(pstate->type == syntax_element_recurse); 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: // Backup call stack:
// //
push_recursion_pop(); push_recursion_pop();
@ -968,6 +981,7 @@ bool perl_matcher<BidiIterator, Allocator, traits>::match_recursion()
recursion_stack.back().results = *m_presult; recursion_stack.back().results = *m_presult;
pstate = static_cast<const re_jump*>(pstate)->alt.p; pstate = static_cast<const re_jump*>(pstate)->alt.p;
recursion_stack.back().idx = static_cast<const re_brace*>(pstate)->index; 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) //if(static_cast<const re_recurse*>(pstate)->state_id > 0)
{ {
push_repeater_count(-(2 + static_cast<const re_brace*>(pstate)->index), &next_count); 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); 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.push_back(recursion_info<results_type>());
recursion_stack.back().preturn_address = pstate->next.p; recursion_stack.back().preturn_address = pstate->next.p;
recursion_stack.back().results = *m_presult; recursion_stack.back().results = *m_presult;
recursion_stack.back().repeater_stack = next_count; recursion_stack.back().repeater_stack = next_count;
recursion_stack.back().location_of_start = position;
pstate = static_cast<const re_jump*>(pstate)->alt.p; pstate = static_cast<const re_jump*>(pstate)->alt.p;
recursion_stack.back().idx = static_cast<const re_brace*>(pstate)->index; recursion_stack.back().idx = static_cast<const re_brace*>(pstate)->index;

View File

@ -434,5 +434,17 @@ void test_tricky_cases3()
test(char(0), test_regex_search_tag()); test(char(0), test_regex_search_tag());
}while(0); }while(0);
#endif #endif
do {
const unsigned char bytes[] = { 0x15,0x0,0x28,0x28,0x85,0x7c,0xb5,0x7c,0x7c,0x7c,0x7c,0x0,0x7c,0x7c,0x16,0x7c,0x7c,0x7c,0x67,0x85,0x0,0xb5,0x7c,0x7c,0x7c,0x7c,0x7c,0x7c,0x7c,0x7c,0x7c,0x7c,0x7c,0x3d,0x0,0x7c,0x7c,0x29,0x3f,0x28,0x3f,0x31,0x29,0xb5,0x2a,0xb5,0xff,0xb5,0xb5,0x85,0xb5,0x67,0xa,0x2a,0xf7,0x2a,0x7c,0x7c,0x32,0x29,0x5c,0x5a,0x3a,0x6b };
std::string str((char*)bytes, sizeof(bytes));
test_info<char>::set_info(__FILE__, __LINE__,
str.c_str(),
perl, str.c_str(), match_default | match_not_dot_newline,
make_array(0, 1, -2, -2));
test(char(0), test_regex_search_tag());
} while(0);
} }