Blob Blame History Raw
From 13f27cb3dee86772eeed5d7d9b47746395ee603c Mon Sep 17 00:00:00 2001
From: Father Chrysostomos <sprout@cpan.org>
Date: Wed, 19 Sep 2012 21:53:51 -0700
Subject: [PATCH] Stop my vars with attrs from leaking
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit

Ported to 5.16.1:

commit 9fa29fa7929b4167c5491b792c5cc7e4365a2839
Author: Father Chrysostomos <sprout@cpan.org>
Date:   Wed Sep 19 21:53:51 2012 -0700

    [perl #114764] Stop my vars with attrs from leaking

S_apply_attrs was creating a SV containing a stash name, that was
later to be put in a const op, which would take care of freeing it.
But it didn’t free it for a my variable, because the branch where that
const op was created didn’t apply.  So move the creation of that SV
inside the branch that uses it, otherwise it leaks.  This leak was the
result of commit 95f0a2f1ffc6.
---
 op.c          | 4 ++--
 t/op/svleak.t | 5 ++++-
 2 files changed, 6 insertions(+), 3 deletions(-)

diff --git a/op.c b/op.c
index 24d5ecb..017580d 100644
--- a/op.c
+++ b/op.c
@@ -2279,13 +2279,11 @@ STATIC void
 S_apply_attrs(pTHX_ HV *stash, SV *target, OP *attrs, bool for_my)
 {
     dVAR;
-    SV *stashsv;
 
     PERL_ARGS_ASSERT_APPLY_ATTRS;
 
     /* fake up C<use attributes $pkg,$rv,@attrs> */
     ENTER;		/* need to protect against side-effects of 'use' */
-    stashsv = stash ? newSVhek(HvNAME_HEK(stash)) : &PL_sv_no;
 
 #define ATTRSMODULE "attributes"
 #define ATTRSMODULE_PM "attributes.pm"
@@ -2300,6 +2298,8 @@ S_apply_attrs(pTHX_ HV *stash, SV *target, OP *attrs, bool for_my)
 			     newSVpvs(ATTRSMODULE), NULL);
     }
     else {
+	SV * const stashsv =
+	    stash ? newSVhek(HvNAME_HEK(stash)) : &PL_sv_no;
 	Perl_load_module(aTHX_ PERL_LOADMOD_IMPORT_OPS,
 			 newSVpvs(ATTRSMODULE),
 			 NULL,
diff --git a/t/op/svleak.t b/t/op/svleak.t
index df10953..6cfee2e 100644
--- a/t/op/svleak.t
+++ b/t/op/svleak.t
@@ -13,7 +13,7 @@ BEGIN {
 	or skip_all("XS::APItest not available");
 }
 
-plan tests => 21;
+plan tests => 22;
 
 # run some code N times. If the number of SVs at the end of loop N is
 # greater than (N-1)*delta at the end of loop 1, we've got a leak
@@ -160,3 +160,6 @@ leak(2, 0,
 }
 
 leak(2,0,sub { !$^V }, '[perl #109762] version object in boolean context');
+
+# [perl #114764] Attributes leak scalars
+leak(2, 0, sub { eval 'my $x : shared' }, 'my $x :shared used to leak');
-- 
1.7.11.4