diff options
author | Yves Orton <demerphq@gmail.com> | 2022-03-13 07:22:36 +0100 |
---|---|---|
committer | Yves Orton <demerphq@gmail.com> | 2022-04-08 12:29:21 +0800 |
commit | 559e5981da7075e9e2c4d0b4fd37eed37718b12a (patch) | |
tree | c0b9c703597d952ec454fd818c0c48ec2c2ab600 /t/re | |
parent | 02ae92405527bc342059f65d0665647b7d5a7ec9 (diff) | |
download | perl-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.t | 44 |
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'; |