Fix bug that effects recursive expressions combined with repeats.

[SVN r58722]
This commit is contained in:
John Maddock
2010-01-05 18:04:08 +00:00
parent f7e16093de
commit 0e1e9804da
6 changed files with 63 additions and 4 deletions

View File

@ -811,8 +811,43 @@ void basic_regex_creator<charT, traits>::fixup_recursions(re_syntax_base* state)
{ {
if((p->type == syntax_element_startmark) && (static_cast<re_brace*>(p)->index == id)) if((p->type == syntax_element_startmark) && (static_cast<re_brace*>(p)->index == id))
{ {
//
// We've found the target of the recursion, set the jump target:
//
static_cast<re_jump*>(state)->alt.p = p; static_cast<re_jump*>(state)->alt.p = p;
ok = true; ok = true;
//
// Now scan the target for nested repeats:
//
p = p->next.p;
int next_rep_id = 0;
while(p)
{
switch(p->type)
{
case syntax_element_rep:
case syntax_element_dot_rep:
case syntax_element_char_rep:
case syntax_element_short_set_rep:
case syntax_element_long_set_rep:
next_rep_id = static_cast<re_repeat*>(p)->state_id;
break;
case syntax_element_endmark:
if(static_cast<const re_brace*>(p)->index == id)
next_rep_id = -1;
break;
default:
break;
}
if(next_rep_id)
break;
p = p->next.p;
}
if(next_rep_id > 0)
{
static_cast<re_recurse*>(state)->state_id = next_rep_id - 1;
}
break; break;
} }
p = p->next.p; p = p->next.p;

View File

@ -1939,7 +1939,9 @@ bool basic_regex_parser<charT, traits>::parse_perl_extension()
} }
insert_recursion: insert_recursion:
pb->index = markid = 0; pb->index = markid = 0;
static_cast<re_jump*>(this->append_state(syntax_element_recurse, sizeof(re_jump)))->alt.i = v; re_recurse* pr = static_cast<re_recurse*>(this->append_state(syntax_element_recurse, sizeof(re_recurse)));
pr->alt.i = v;
pr->state_id = 0;
static_cast<re_case*>( static_cast<re_case*>(
this->append_state(syntax_element_toggle_case, sizeof(re_case)) this->append_state(syntax_element_toggle_case, sizeof(re_case))
)->icase = this->flags() & regbase::icase; )->icase = this->flags() & regbase::icase;

View File

@ -277,11 +277,16 @@ public:
else else
{ {
repeater_count* p = next; repeater_count* p = next;
while(p->state_id != state_id) while(p && (p->state_id != state_id))
p = p->next; p = p->next;
if(p)
{
count = p->count; count = p->count;
start_pos = p->start_pos; start_pos = p->start_pos;
} }
else
count = 0;
}
} }
~repeater_count() ~repeater_count()
{ {

View File

@ -904,10 +904,15 @@ bool perl_matcher<BidiIterator, Allocator, traits>::match_recursion()
} }
recursion_stack[recursion_stack_position].preturn_address = pstate->next.p; recursion_stack[recursion_stack_position].preturn_address = pstate->next.p;
recursion_stack[recursion_stack_position].results = *m_presult; recursion_stack[recursion_stack_position].results = *m_presult;
if(static_cast<const re_recurse*>(pstate)->state_id > 0)
{
push_repeater_count(static_cast<const re_recurse*>(pstate)->state_id, &next_count);
}
pstate = static_cast<const re_jump*>(pstate)->alt.p; pstate = static_cast<const re_jump*>(pstate)->alt.p;
recursion_stack[recursion_stack_position].id = static_cast<const re_brace*>(pstate)->index; recursion_stack[recursion_stack_position].id = static_cast<const re_brace*>(pstate)->index;
++recursion_stack_position; ++recursion_stack_position;
//BOOST_ASSERT(recursion_stack[recursion_stack_position-1].id); //BOOST_ASSERT(recursion_stack[recursion_stack_position-1].id);
return true; return true;
} }

View File

@ -248,6 +248,14 @@ struct re_repeat : public re_alt
bool greedy; // True if this is a greedy repeat bool greedy; // True if this is a greedy repeat
}; };
/*** struct re_recurse ************************************************
Recurse to a particular subexpression.
**********************************************************************/
struct re_recurse : public re_jump
{
int state_id; // identifier of first nested repeat within the recursion.
};
/*** enum re_jump_size_type ******************************************* /*** enum re_jump_size_type *******************************************
Provides compiled size of re_jump structure (allowing for trailing alignment). Provides compiled size of re_jump structure (allowing for trailing alignment).
We provide this so we know how manybytes to insert when constructing the machine We provide this so we know how manybytes to insert when constructing the machine

View File

@ -892,5 +892,9 @@ void test_recursion()
TEST_REGEX_SEARCH("\\b(?&byte)(\\.(?&byte)){3}(?(DEFINE)(?<byte>2[0-4]\\d|25[0-5]|1\\d\\d|[1-9]?\\d))", perl|mod_x, "10.0.0.0", match_default, make_array(0, 8, 6, 8, -1, -1, -2, -2)); TEST_REGEX_SEARCH("\\b(?&byte)(\\.(?&byte)){3}(?(DEFINE)(?<byte>2[0-4]\\d|25[0-5]|1\\d\\d|[1-9]?\\d))", perl|mod_x, "10.0.0.0", match_default, make_array(0, 8, 6, 8, -1, -1, -2, -2));
TEST_REGEX_SEARCH("\\b(?&byte)(\\.(?&byte)){3}(?(DEFINE)(?<byte>2[0-4]\\d|25[0-5]|1\\d\\d|[1-9]?\\d))", perl|mod_x, "10.6", match_default, make_array(-2, -2)); TEST_REGEX_SEARCH("\\b(?&byte)(\\.(?&byte)){3}(?(DEFINE)(?<byte>2[0-4]\\d|25[0-5]|1\\d\\d|[1-9]?\\d))", perl|mod_x, "10.6", match_default, make_array(-2, -2));
TEST_REGEX_SEARCH("\\b(?&byte)(\\.(?&byte)){3}(?(DEFINE)(?<byte>2[0-4]\\d|25[0-5]|1\\d\\d|[1-9]?\\d))", perl|mod_x, "455.3.4.5", match_default, make_array(-2, -2)); TEST_REGEX_SEARCH("\\b(?&byte)(\\.(?&byte)){3}(?(DEFINE)(?<byte>2[0-4]\\d|25[0-5]|1\\d\\d|[1-9]?\\d))", perl|mod_x, "455.3.4.5", match_default, make_array(-2, -2));
// Bugs:
TEST_REGEX_SEARCH("namespace\\s+(\\w+)\\s+(\\{(?:[^{}]*(?:(?2)[^{}]*)*)?\\})", perl, "namespace one { namespace two { int foo(); } }", match_default, make_array(0, 46, 10, 13, 14, 46, -2, -2));
TEST_REGEX_SEARCH("namespace\\s+(\\w+)\\s+(\\{(?:[^{}]*(?:(?2)[^{}]*)*)?\\})", perl, "namespace one { namespace two { int foo(){} } { {{{ } } } } {}}", match_default, make_array(0, 64, 10, 13, 14, 64, -2, -2));
} }