1b39c5158Smillert#!./perl 2898184e3Ssthen 391f110e0Safresh1print "1..14\n"; 4898184e3Ssthen 5b39c5158Smillert# Tests bug #22977. Test case from Dave Mitchell. 6b39c5158Smillertsub f ($); 7b39c5158Smillertsub f ($) { 8b39c5158Smillertmy $test = $_[0]; 9b39c5158Smillertwrite; 10b39c5158Smillertformat STDOUT = 11b39c5158Smillertok @<<<<<<< 12b39c5158Smillert$test 13b39c5158Smillert. 14b39c5158Smillert} 15b39c5158Smillert 16b39c5158Smillertf(1); 17b39c5158Smillertf(2); 18898184e3Ssthen 19898184e3Ssthen# A bug caused by the fix for #22977/50528 20898184e3Ssthensub foo { 21898184e3Ssthen sub bar { 22898184e3Ssthen # Fill the pad with alphabet soup, to give the closed-over variable a 23898184e3Ssthen # high padoffset (more likely to trigger the bug and crash). 24898184e3Ssthen {my ($a,$b,$c,$d,$e,$f,$g,$h,$i,$j,$k,$l,$m,$n,$o,$p,$q,$r,$s,$t,$u)} 25898184e3Ssthen {my ($a,$b,$c,$d,$e,$f,$g,$h,$i,$j,$k,$l,$m,$n,$o,$p,$q,$r,$s,$t,$u)} 26898184e3Ssthen {my ($a,$b,$c,$d,$e,$f,$g,$h,$i,$j,$k,$l,$m,$n,$o,$p,$q,$r,$s,$t,$u)} 27898184e3Ssthen {my ($a,$b,$c,$d,$e,$f,$g,$h,$i,$j,$k,$l,$m,$n,$o,$p,$q,$r,$s,$t,$u)} 28898184e3Ssthen {my ($a,$b,$c,$d,$e,$f,$g,$h,$i,$j,$k,$l,$m,$n,$o,$p,$q,$r,$s,$t,$u)} 29898184e3Ssthen {my ($a,$b,$c,$d,$e,$f,$g,$h,$i,$j,$k,$l,$m,$n,$o,$p,$q,$r,$s,$t,$u)} 30898184e3Ssthen {my ($a,$b,$c,$d,$e,$f,$g,$h,$i,$j,$k,$l,$m,$n,$o,$p,$q,$r,$s,$t,$u)} 31898184e3Ssthen {my ($a,$b,$c,$d,$e,$f,$g,$h,$i,$j,$k,$l,$m,$n,$o,$p,$q,$r,$s,$t,$u)} 32898184e3Ssthen {my ($a,$b,$c,$d,$e,$f,$g,$h,$i,$j,$k,$l,$m,$n,$o,$p,$q,$r,$s,$t,$u)} 33898184e3Ssthen {my ($a,$b,$c,$d,$e,$f,$g,$h,$i,$j,$k,$l,$m,$n,$o,$p,$q,$r,$s,$t,$u)} 34898184e3Ssthen {my ($a,$b,$c,$d,$e,$f,$g,$h,$i,$j,$k,$l,$m,$n,$o,$p,$q,$r,$s,$t,$u)} 35898184e3Ssthen {my ($a,$b,$c,$d,$e,$f,$g,$h,$i,$j,$k,$l,$m,$n,$o,$p,$q,$r,$s,$t,$u)} 36898184e3Ssthen {my ($a,$b,$c,$d,$e,$f,$g,$h,$i,$j,$k,$l,$m,$n,$o,$p,$q,$r,$s,$t,$u)} 37898184e3Ssthen {my ($a,$b,$c,$d,$e,$f,$g,$h,$i,$j,$k,$l,$m,$n,$o,$p,$q,$r,$s,$t,$u)} 38898184e3Ssthen {my ($a,$b,$c,$d,$e,$f,$g,$h,$i,$j,$k,$l,$m,$n,$o,$p,$q,$r,$s,$t,$u)} 39898184e3Ssthen {my ($a,$b,$c,$d,$e,$f,$g,$h,$i,$j,$k,$l,$m,$n,$o,$p,$q,$r,$s,$t,$u)} 40898184e3Ssthen {my ($a,$b,$c,$d,$e,$f,$g,$h,$i,$j,$k,$l,$m,$n,$o,$p,$q,$r,$s,$t,$u)} 41898184e3Ssthen {my ($a,$b,$c,$d,$e,$f,$g,$h,$i,$j,$k,$l,$m,$n,$o,$p,$q,$r,$s,$t,$u)} 42898184e3Ssthen my $x; 43898184e3Ssthen format STDOUT2 = 44898184e3Ssthen@<<<<<< 45898184e3Ssthen"ok 3".$x # $x is not available, but this should not crash 46898184e3Ssthen. 47898184e3Ssthen } 48898184e3Ssthen} 49898184e3Ssthen*STDOUT = *STDOUT2{FORMAT}; 50898184e3Ssthenundef *bar; 51898184e3Ssthenwrite; 52898184e3Ssthen 53898184e3Ssthen# A regression introduced in 5.10; format cloning would close over the 54898184e3Ssthen# variables in the currently-running sub (the main CV in this test) if the 55898184e3Ssthen# outer sub were an inactive closure. 56898184e3Ssthensub baz { 57898184e3Ssthen my $a; 58898184e3Ssthen sub { 59898184e3Ssthen $a; 60898184e3Ssthen {my ($a,$b,$c,$d,$e,$f,$g,$h,$i,$j,$k,$l,$m,$n,$o,$p,$q,$r,$s,$t)} 61898184e3Ssthen my $x; 62898184e3Ssthen format STDOUT3 = 63898184e3Ssthen@<<<<<<<<<<<<<<<<<<<<<<<<< 64898184e3Ssthendefined $x ? "not ok 4 - $x" : "ok 4" 65898184e3Ssthen. 66898184e3Ssthen } 67898184e3Ssthen} 68898184e3Ssthen*STDOUT = *STDOUT3{FORMAT}; 69898184e3Ssthen{ 70898184e3Ssthen local $^W = 1; 71898184e3Ssthen my $w; 72898184e3Ssthen local $SIG{__WARN__} = sub { $w = shift }; 73898184e3Ssthen write; 74898184e3Ssthen print "not " unless $w =~ /^Variable "\$x" is not available at/; 75898184e3Ssthen print "ok 5 - closure var not available when outer sub is inactive\n"; 76898184e3Ssthen} 77898184e3Ssthen 7891f110e0Safresh1# Formats inside closures should close over the topmost clone of the outer 7991f110e0Safresh1# sub on the call stack. 8091f110e0Safresh1# Tests will be out of sequence if the wrong sub is used. 8191f110e0Safresh1sub make_closure { 8291f110e0Safresh1 my $arg = shift; 8391f110e0Safresh1 sub { 8491f110e0Safresh1 shift == 0 and &$next(1), return; 8591f110e0Safresh1 my $x = "ok $arg"; 8691f110e0Safresh1 format STDOUT4 = 8791f110e0Safresh1@<<<<<<< 8891f110e0Safresh1$x 8991f110e0Safresh1. 9091f110e0Safresh1 sub { write }->(); # separate sub, so as not to rely on it being the 9191f110e0Safresh1 } # currently-running sub 9291f110e0Safresh1} 9391f110e0Safresh1*STDOUT = *STDOUT4{FORMAT}; 9491f110e0Safresh1$clo1 = make_closure 6; 9591f110e0Safresh1$clo2 = make_closure 7; 9691f110e0Safresh1$next = $clo1; 9791f110e0Safresh1&$clo2(0); 9891f110e0Safresh1$next = $clo2; 9991f110e0Safresh1&$clo1(0); 10091f110e0Safresh1 101898184e3Ssthen# Cloning a format whose outside has been undefined 102898184e3Ssthensub x { 103898184e3Ssthen {my ($a,$b,$c,$d,$e,$f,$g,$h,$i,$j,$k,$l,$m,$n,$o,$p,$q,$r,$s,$t,$u)} 104898184e3Ssthen my $z; 105898184e3Ssthen format STDOUT6 = 106898184e3Ssthen@<<<<<<<<<<<<<<<<<<<<<<<<< 10791f110e0Safresh1defined $z ? "not ok 8 - $z" : "ok 8" 108898184e3Ssthen. 109898184e3Ssthen} 110898184e3Ssthenundef &x; 111898184e3Ssthen*STDOUT = *STDOUT6{FORMAT}; 112898184e3Ssthen{ 113898184e3Ssthen local $^W = 1; 114898184e3Ssthen my $w; 115898184e3Ssthen local $SIG{__WARN__} = sub { $w = shift }; 116898184e3Ssthen write; 117898184e3Ssthen print "not " unless $w =~ /^Variable "\$z" is not available at/; 11891f110e0Safresh1 print "ok 9 - closure var not available when outer sub is undefined\n"; 11991f110e0Safresh1} 12091f110e0Safresh1 12191f110e0Safresh1format STDOUT7 = 12291f110e0Safresh1@<<<<<<<<<<<<<<<<<<<<<<<<<<< 12391f110e0Safresh1do { my $x = "ok 10 - closure inside format"; sub { $x }->() } 12491f110e0Safresh1. 12591f110e0Safresh1*STDOUT = *STDOUT7{FORMAT}; 12691f110e0Safresh1write; 12791f110e0Safresh1 12891f110e0Safresh1$testn = 12; 12991f110e0Safresh1format STDOUT8 = 13091f110e0Safresh1@<<<< - recursive formats 13191f110e0Safresh1do { my $t = "ok " . $testn--; write if $t =~ 12; $t} 13291f110e0Safresh1. 13391f110e0Safresh1*STDOUT = *STDOUT8{FORMAT}; 13491f110e0Safresh1write; 13591f110e0Safresh1 13691f110e0Safresh1sub _13 { 13791f110e0Safresh1 my $x; 13891f110e0Safresh1format STDOUT13 = 139*b8851fccSafresh1@* - formats closing over redefined subs (got @*) 140*b8851fccSafresh1ref \$x eq 'SCALAR' ? "ok 13" : "not ok 13", ref \$x; 14191f110e0Safresh1. 14291f110e0Safresh1} 14391f110e0Safresh1undef &_13; 14491f110e0Safresh1eval 'sub _13 { my @x; write }'; 14591f110e0Safresh1*STDOUT = *STDOUT13{FORMAT}; 14691f110e0Safresh1_13(); 14791f110e0Safresh1 14891f110e0Safresh1# This is a variation of bug #22977, which crashes or fails an assertion 14991f110e0Safresh1# up to 5.16. 15091f110e0Safresh1# Keep this test last if you want test numbers to be sane. 15191f110e0Safresh1BEGIN { \&END } 15291f110e0Safresh1END { 15391f110e0Safresh1 my $test = "ok 14"; 15491f110e0Safresh1 *STDOUT = *STDOUT5{FORMAT}; 15591f110e0Safresh1 write; 15691f110e0Safresh1 format STDOUT5 = 15791f110e0Safresh1@<<<<<<< 15891f110e0Safresh1$test 15991f110e0Safresh1. 160898184e3Ssthen} 161