diff options
author | David Mitchell <davem@iabyn.com> | 2017-02-14 15:59:57 +0000 |
---|---|---|
committer | David Mitchell <davem@iabyn.com> | 2017-02-14 17:49:58 +0000 |
commit | 4ee16520199a0e11bf4dbdbac71f0a64e5510271 (patch) | |
tree | 3798512c4f271dc8c418b10a336811ed377c101a /t | |
parent | f4197b8e1d1f984eb6635ea41ce14394432b96b1 (diff) | |
download | perl-4ee16520199a0e11bf4dbdbac71f0a64e5510271.tar.gz |
clear savestack on (?{...}) failure and backtrack
RT #126697
In a regex, after executing a (?{...}) code block, if we fail and
backtrack over the codeblock, we're supposed to unwind the savestack, so
that for any example any local()s within the code block are undone.
It turns out that a backtracking state isn't pushed for (?{...}), only
for postponed evals ( i.e. (??{...})). This means that it relies on one
of the earlier backtracking states to clear the savestack on its behalf.
This can't always be relied upon, and the ticket above contains code where
this falls down; in particular:
'ABC' =~ m{
\A
(?:
(?: AB | A | BC )
(?{
local $count = $count + 1;
print "! count=$count; ; pos=${\pos}\n";
})
)*
\z
}x
Here we end up relying on TRIE_next to do the cleaning up, but TRIE_next
doesn't, since there's nothing it would be responsible for that needs
cleaning up.
The solution to this is to push a backtrack state for every (?{...}) as
well as every (??{...}). The sole job of that state is to do a
LEAVE_SCOPE(ST.lastcp).
The existing backtrack state EVAL_AB has been renamed EVAL_postponed_AB
to make it clear it's only used on postponed /(??{A})B/ regexes, and a new
state has been added, EVAL_B, which is only called when backtracking after
failing something in the B in /(?{...})B/.
Diffstat (limited to 't')
-rw-r--r-- | t/re/pat_re_eval.t | 22 |
1 files changed, 21 insertions, 1 deletions
diff --git a/t/re/pat_re_eval.t b/t/re/pat_re_eval.t index f23a79c51b..6921d38bac 100644 --- a/t/re/pat_re_eval.t +++ b/t/re/pat_re_eval.t @@ -22,7 +22,7 @@ BEGIN { } -plan tests => 532; # Update this when adding/deleting tests. +plan tests => 533; # Update this when adding/deleting tests. run_tests() unless caller; @@ -1271,6 +1271,26 @@ sub run_tests { }->(); + # RT #126697 + # savestack wasn't always being unwound on EVAL failure + { + local our $i = 0; + my $max = 0; + + 'ABC' =~ m{ + \A + (?: + (?: AB | A | BC ) + (?{ + local $i = $i + 1; + $max = $i if $max < $i; + }) + )* + \z + }x; + is $max, 2, "RT #126697"; + } + } # End of sub run_tests |