[perl #3112] Stop last from returning values
authorFather Chrysostomos <sprout@cpan.org>
Fri, 20 Sep 2013 08:34:31 +0000 (01:34 -0700)
committerFather Chrysostomos <sprout@cpan.org>
Fri, 20 Sep 2013 19:44:39 +0000 (12:44 -0700)
In push @a, last, it can try to return the @a, copying it like a sca-
lar in the process, resulting in Bizarre copy of ARRAY in last.

In do{{&{sub{"Just another Perl hacker,\n"}},last}}, it returns "Just
another Perl hacker,\n".

The former is clearly a bug.  The latter depends on a side-effect of
the same bug.

‘last’ really should not be trying to return the values that the same
statement has accumulated so far.

pp_ctl.c
t/op/loopctl.t

index 2144fab..63482fd 100644 (file)
--- a/pp_ctl.c
+++ b/pp_ctl.c
@@ -2616,7 +2616,6 @@ PP(pp_last)
 
     POPBLOCK(cx,newpm);
     cxstack_ix++; /* temporarily protect top context */
-    mark = newsp;
     switch (CxTYPE(cx)) {
     case CXt_LOOP_LAZYIV:
     case CXt_LOOP_LAZYSV:
@@ -2643,8 +2642,7 @@ PP(pp_last)
     }
 
     TAINT_NOT;
-    PL_stack_sp = adjust_stack_on_leave(newsp, PL_stack_sp, MARK, gimme,
-                               pop2 == CXt_SUB ? SVs_TEMP : 0);
+    PL_stack_sp = newsp;
 
     LEAVE;
     cxstack_ix--;
index fcb1237..d520a7f 100644 (file)
 BEGIN {
     chdir 't' if -d 't';
     @INC = qw(. ../lib);
+    require "test.pl";
 }
 
-require "test.pl";
-plan( tests => 64 );
+plan( tests => 67 );
 
 my $ok;
 
@@ -1104,3 +1104,17 @@ redo_113684:
         fail("redo with non-constant label");
     }
 }
+
+# [perl #3112]
+# The original report, which produced a Bizarre copy
+@a  = ();
+eval {
+    for (1) {
+        push @a, last;
+    }
+};
+is @a, 0, 'push @a, last;  does not push';
+is $@, "", 'no error, either';
+# And my japh, which relied on the misbehaviour
+is do{{&{sub{"Just another Perl hacker,\n"}},last}}, undef,
+  'last returns nothing';