summaryrefslogtreecommitdiff
path: root/t
diff options
context:
space:
mode:
authorDavid Mitchell <davem@iabyn.com>2017-02-14 15:59:57 +0000
committerDavid Mitchell <davem@iabyn.com>2017-02-14 17:49:58 +0000
commit4ee16520199a0e11bf4dbdbac71f0a64e5510271 (patch)
tree3798512c4f271dc8c418b10a336811ed377c101a /t
parentf4197b8e1d1f984eb6635ea41ce14394432b96b1 (diff)
downloadperl-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.t22
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