diff --git a/include/boost/regex/v4/perl_matcher.hpp b/include/boost/regex/v4/perl_matcher.hpp index b1434d07..32517c62 100644 --- a/include/boost/regex/v4/perl_matcher.hpp +++ b/include/boost/regex/v4/perl_matcher.hpp @@ -348,6 +348,7 @@ struct recursion_info const re_syntax_base* preturn_address; Results results; repeater_count* repeater_stack; + iterator location_of_start; }; #ifdef BOOST_MSVC diff --git a/include/boost/regex/v4/perl_matcher_non_recursive.hpp b/include/boost/regex/v4/perl_matcher_non_recursive.hpp index aa7af3b4..93750247 100644 --- a/include/boost/regex/v4/perl_matcher_non_recursive.hpp +++ b/include/boost/regex/v4/perl_matcher_non_recursive.hpp @@ -953,6 +953,19 @@ bool perl_matcher::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 >::const_reverse_iterator i = recursion_stack.rbegin(); i != recursion_stack.rend(); ++i) + { + if(i->idx == static_cast(static_cast(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::match_recursion() recursion_stack.back().results = *m_presult; pstate = static_cast(pstate)->alt.p; recursion_stack.back().idx = static_cast(pstate)->index; + recursion_stack.back().location_of_start = position; //if(static_cast(pstate)->state_id > 0) { push_repeater_count(-(2 + static_cast(pstate)->index), &next_count); diff --git a/include/boost/regex/v4/perl_matcher_recursive.hpp b/include/boost/regex/v4/perl_matcher_recursive.hpp index 33b91581..ef163d75 100644 --- a/include/boost/regex/v4/perl_matcher_recursive.hpp +++ b/include/boost/regex/v4/perl_matcher_recursive.hpp @@ -900,10 +900,27 @@ bool perl_matcher::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 >::const_reverse_iterator i = recursion_stack.rbegin(); i != recursion_stack.rend(); ++i) + { + if(i->idx == static_cast(static_cast(pstate)->alt.p)->index) + { + if(i->location_of_start == position) + return false; + break; + } + } + // + // Now get on with it: + // recursion_stack.push_back(recursion_info()); 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(pstate)->alt.p; recursion_stack.back().idx = static_cast(pstate)->index; diff --git a/test/regress/test_tricky_cases.cpp b/test/regress/test_tricky_cases.cpp index 033c3dea..f9cc25d1 100644 --- a/test/regress/test_tricky_cases.cpp +++ b/test/regress/test_tricky_cases.cpp @@ -434,5 +434,17 @@ void test_tricky_cases3() test(char(0), test_regex_search_tag()); }while(0); #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::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); + + }