state variables shouldn't be shared between anon subs
Dave Mitchell [Sun, 9 Sep 2007 19:51:50 +0000 (19:51 +0000)]
p4raw-id: //depot/perl@31833

op.c
t/op/state.t

diff --git a/op.c b/op.c
index ca488a2..1ebc84c 100644 (file)
--- a/op.c
+++ b/op.c
@@ -395,6 +395,12 @@ Perl_allocmy(pTHX_ const char *const name)
                    0, /*  not fake */
                    PL_parser->in_my == KEY_state
     );
+    /* anon sub prototypes contains state vars should always be cloned,
+     * otherwise the state var would be shared between anon subs */
+
+    if (PL_parser->in_my == KEY_state && CvANON(PL_compcv))
+       CvCLONE_on(PL_compcv);
+
     return off;
 }
 
index 6d835c4..c372bf6 100644 (file)
@@ -10,7 +10,7 @@ BEGIN {
 use strict;
 use feature ":5.10";
 
-plan tests => 117;
+plan tests => 119;
 
 ok( ! defined state $uninit, q(state vars are undef by default) );
 
@@ -321,6 +321,18 @@ foreach my $spam (@spam) {
     is $x, "two", "masked"
 }
 
+# normally closureless anon subs share a CV and pad. If the anon sub has a
+# state var, this would mean that it is shared. Check that this doesn't
+# happen
+
+{
+    my @f;
+    push @f, sub { state $x; ++$x } for 1..2;
+    $f[0]->() for 1..10;
+    is $f[0]->(), 11;
+    is $f[1]->(), 1;
+}
+
 foreach my $forbidden (<DATA>) {
     chomp $forbidden;
     no strict 'vars';