This is a live mirror of the Perl 5 development currently hosted at https://github.com/perl/perl5
[perl #35214] SEGV when next is followed by a goto
authorDave Mitchell <davem@fdisolutions.com>
Wed, 4 May 2005 14:01:40 +0000 (14:01 +0000)
committerDave Mitchell <davem@fdisolutions.com>
Wed, 4 May 2005 14:01:40 +0000 (14:01 +0000)
next and redo didn't restore PL_curcop

p4raw-id: //depot/perl@24384

pp_ctl.c
t/op/goto.t

index c4aa30e..03a4171 100644 (file)
--- a/pp_ctl.c
+++ b/pp_ctl.c
@@ -1890,6 +1890,7 @@ PP(pp_leaveloop)
     SV **mark;
 
     POPBLOCK(cx,newpm);
     SV **mark;
 
     POPBLOCK(cx,newpm);
+    assert(CxTYPE(cx) == CXt_LOOP);
     mark = newsp;
     newsp = PL_stack_base + cx->blk_loop.resetsp;
 
     mark = newsp;
     newsp = PL_stack_base + cx->blk_loop.resetsp;
 
@@ -2149,6 +2150,7 @@ PP(pp_next)
     TOPBLOCK(cx);
     if (PL_scopestack_ix < inner)
        leave_scope(PL_scopestack[PL_scopestack_ix]);
     TOPBLOCK(cx);
     if (PL_scopestack_ix < inner)
        leave_scope(PL_scopestack[PL_scopestack_ix]);
+    PL_curcop = cx->blk_oldcop;
     return cx->blk_loop.next_op;
 }
 
     return cx->blk_loop.next_op;
 }
 
@@ -2176,6 +2178,7 @@ PP(pp_redo)
     oldsave = PL_scopestack[PL_scopestack_ix - 1];
     LEAVE_SCOPE(oldsave);
     FREETMPS;
     oldsave = PL_scopestack[PL_scopestack_ix - 1];
     LEAVE_SCOPE(oldsave);
     FREETMPS;
+    PL_curcop = cx->blk_oldcop;
     return cx->blk_loop.redo_op;
 }
 
     return cx->blk_loop.redo_op;
 }
 
index 3b92123..806dbed 100755 (executable)
@@ -7,7 +7,7 @@ BEGIN {
     @INC = qw(. ../lib);
 }
 
     @INC = qw(. ../lib);
 }
 
-print "1..47\n";
+print "1..49\n";
 
 require "test.pl";
 
 
 require "test.pl";
 
@@ -414,5 +414,27 @@ sub b32039 { goto &c32039; }
 sub c32039 { print $_[0] eq 'foo' ? "" : "not ", "ok 47 - chained &goto\n" }
 a32039();
 
 sub c32039 { print $_[0] eq 'foo' ? "" : "not ", "ok 47 - chained &goto\n" }
 a32039();
 
+# [perl #35214] next and redo re-entered the loop with the wrong cop,
+# causing a subsequent goto to crash
+
+{
+    my $r = runperl(
+               stderr => 1,
+               prog =>
+'for ($_=0;$_<3;$_++){A: if($_==1){next} if($_==2){$_++;goto A}}print qq(ok)'
+    );
+    $r =~ s/\n//g;
+    print "# r=$r\nnot " unless $r eq 'ok';
+    print "ok 48 - next and goto\n";
+
+    $r = runperl(
+               stderr => 1,
+               prog =>
+'for ($_=0;$_<3;$_++){A: if($_==1){$_++;redo} if($_==2){$_++;goto A}}print qq(ok)'
+    );
+    $r =~ s/\n//g;
+    print "# r=$r\nnot " unless $r eq 'ok';
+    print "ok 49 - redo and goto\n";
+}