summaryrefslogtreecommitdiff
path: root/t/re
diff options
context:
space:
mode:
authorYves Orton <demerphq@gmail.com>2022-03-13 07:22:36 +0100
committerYves Orton <demerphq@gmail.com>2022-04-08 12:29:21 +0800
commit559e5981da7075e9e2c4d0b4fd37eed37718b12a (patch)
treec0b9c703597d952ec454fd818c0c48ec2c2ab600 /t/re
parent02ae92405527bc342059f65d0665647b7d5a7ec9 (diff)
downloadperl-559e5981da7075e9e2c4d0b4fd37eed37718b12a.tar.gz
regexec.c: make ACCEPT close logic handle SUCCEED/LOOKBEHIND_END opcodes
GH Issue #19484 reported that print "ABDE" =~ /(A (A|B(*ACCEPT)|C)+ D)(E)/x ? "yes: <$1-$2>" : "no"; does not output the expected 'AB-B', and instead does not match. Removing the + quantifier behaves as expected. This patch is 4/4 of the patches to fix this problem: SUCCEED and LOOKBEHIND_END regops are type 'END' which have a next_off of 0. This was causing regnext() to return null inside of the loop iterator for the logic in ACCEPT which closes any open capture buffers thus terminating the loop prematurely and preventing some of the capture buffers from being properly closed. SUCCEED is used to end a variety of structures, including lookahead IFMATCH and UNLESSM, SUSPEND, and CURLYM, and LOOKBEHIND_END serves the same purpose for lookbehind IFMATCH and UNLESSM. Thus this patch fixes the original bug but also fixes a variety of other cases involving ACCEPT.
Diffstat (limited to 't/re')
-rw-r--r--t/re/pat.t44
1 files changed, 42 insertions, 2 deletions
diff --git a/t/re/pat.t b/t/re/pat.t
index e7e019f7ce..7292e4625a 100644
--- a/t/re/pat.t
+++ b/t/re/pat.t
@@ -27,7 +27,7 @@ skip_all_without_unicode_tables();
my $has_locales = locales_enabled('LC_CTYPE');
-plan tests => 1022; # Update this when adding/deleting tests.
+plan tests => 1046; # Update this when adding/deleting tests.
run_tests() unless caller;
@@ -670,7 +670,47 @@ sub run_tests {
@_ = /(bbb)/g;
is("@_", "", $message);
}
-
+ {
+ my $message = 'ACCEPT and CLOSE - ';
+ $_ = "aced";
+ #12 3 4 5
+ /((a?(*ACCEPT)())())()/
+ or die "Failed to match";
+ is($1,"a",$message . "buffer 1 is defined with expected value");
+ is($2,"a",$message . "buffer 2 is defined with expected value");
+ ok(!defined($3),$message . "buffer 3 is not defined");
+ ok(!defined($4),$message . "buffer 4 is not defined");
+ ok(!defined($5),$message . "buffer 5 is not defined");
+ ok(!defined($6),$message . "buffer 6 is not defined");
+ $message= 'NO ACCEPT and CLOSE - ';
+ /((a?())())()/
+ or die "Failed to match";
+ is($1,"a",$message . "buffer 1 is defined with expected value");
+ is($2,"a",$message . "buffer 2 is defined with expected value");
+ is($3,"", $message . "buffer 3 is defined with expected value");
+ is($4,"", $message . "buffer 4 is defined with expected value");
+ is($5,"",$message . "buffer 5 is defined with expected value");
+ ok(!defined($6),$message . "buffer 6 is not defined");
+ #12 3 4 5
+ $message = 'ACCEPT and CLOSE - ';
+ /((a?(*ACCEPT)(c))(e))(d)/
+ or die "Failed to match";
+ is($1,"a",$message . "buffer 1 is defined with expected value");
+ is($2,"a",$message . "buffer 2 is defined with expected value");
+ ok(!defined($3),$message . "buffer 3 is not defined");
+ ok(!defined($4),$message . "buffer 4 is not defined");
+ ok(!defined($5),$message . "buffer 5 is not defined");
+ ok(!defined($6),$message . "buffer 6 is not defined");
+ $message= 'NO ACCEPT and CLOSE - ';
+ /((a?(c))(e))(d)/
+ or die "Failed to match";
+ is($1,"ace", $message . "buffer 1 is defined with expected value");
+ is($2,"ac", $message . "buffer 2 is defined with expected value");
+ is($3,"c", $message . "buffer 3 is defined with expected value");
+ is($4,"e", $message . "buffer 4 is defined with expected value");
+ is($5,"d", $message . "buffer 5 is defined with expected value");
+ ok(!defined($6),$message . "buffer 6 is not defined");
+ }
{
my $message = '@- and @+ and @{^CAPTURE} tests';