From 92e82afa16f5f1aa1b3e163f6d4656d14c44a4d2 Mon Sep 17 00:00:00 2001 From: Yves Orton Date: Sat, 12 Mar 2011 17:21:54 +0100 Subject: [PATCH] Fix RT #84294 /((\w+)(?{print $2})){2,2}/ problem When we are doing a CURLYX/WHILEM loop and the min iterations is larger than zero we were not saving the buffer state before each iteration. This mean that partial matches would end up with strange buffer pointers, with the start *after* the end point. In more detail WHILEM has four exits, three of which as far as I could tell would do a regcppush/regcppop in their state transitions, only one, WHILEM_A_pre which is entered when (n < min) would not. And it is this state that we repeatedly enter when performing A the min number of times. When I made the logic similar to the handling of ( n < max ), the bug went away, and as far as I can tell nothing else broke. Review by Dave Mitchell required before release. --- regexec.c | 7 +++++-- t/re/pat.t | 1 - 2 files changed, 5 insertions(+), 3 deletions(-) diff --git a/regexec.c b/regexec.c index 8486646..eb5e346 100644 --- a/regexec.c +++ b/regexec.c @@ -4648,7 +4648,10 @@ NULL /* First just match a string of min A's. */ if (n < min) { + ST.cp = regcppush(cur_curlyx->u.curlyx.parenfloor); cur_curlyx->u.curlyx.lastloc = locinput; + REGCP_SET(ST.lastcp); + PUSH_STATE_GOTO(WHILEM_A_pre, A); /* NOTREACHED */ } @@ -4754,10 +4757,10 @@ NULL /* NOTREACHED */ case WHILEM_A_min_fail: /* just failed to match A in a minimal match */ - REGCP_UNWIND(ST.lastcp); - regcppop(rex); /* FALL THROUGH */ case WHILEM_A_pre_fail: /* just failed to match even minimal A */ + REGCP_UNWIND(ST.lastcp); + regcppop(rex); cur_curlyx->u.curlyx.lastloc = ST.save_lastloc; cur_curlyx->u.curlyx.count--; CACHEsayNO; diff --git a/t/re/pat.t b/t/re/pat.t index aa19030..4ef9663 100644 --- a/t/re/pat.t +++ b/t/re/pat.t @@ -1162,7 +1162,6 @@ sub run_tests { # : Nested buffers and (?{...}) dont play nicely on partial matches our @got= (); ok("ab" =~ /((\w+)(?{ push @got, $2 })){2}/,"RT #84294: Pattern should match"); - local $::TODO= "not fixed yet"; my $want= "'ab', 'a', 'b'"; my $got= join(", ", map { defined($_) ? "'$_'" : "undef" } @got); is($got,$want,'RT #84294: check that "ab" =~ /((\w+)(?{ push @got, $2 })){2}/ leaves @got in the correct state'); -- 2.7.4