mirror of
https://github.com/boostorg/regex.git
synced 2025-07-20 07:42:07 +02:00
de-fuzz: prevent infinite recursion in recursive expressions (case 14).
This commit is contained in:
@ -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
|
||||||
|
@ -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);
|
||||||
|
@ -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;
|
||||||
|
|
||||||
|
@ -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);
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Reference in New Issue
Block a user