This is a live mirror of the Perl 5 development currently hosted at https://github.com/perl/perl5
$ref++, $ref-- leaked referent
authorDavid Mitchell <davem@iabyn.com>
Mon, 6 Sep 2010 15:24:47 +0000 (16:24 +0100)
committerDavid Mitchell <davem@iabyn.com>
Mon, 6 Sep 2010 15:28:54 +0000 (16:28 +0100)
[perl #9466]

pp_postinc and pp_postdec used a pad TARG to return a copy of the
original value. When that value was a reference, it meant a copy
of the reference would hang out in the pad forever and so the referent
would leak. Fix this by using a mortal instead.

pp.c
t/op/inc.t

diff --git a/pp.c b/pp.c
index 31614ed..78ed286 100644 (file)
--- a/pp.c
+++ b/pp.c
@@ -899,6 +899,8 @@ PP(pp_postinc)
     dVAR; dSP; dTARGET;
     if (SvTYPE(TOPs) >= SVt_PVAV || isGV_with_GP(TOPs))
        Perl_croak_no_modify(aTHX);
+    if (SvROK(TOPs))
+       TARG = sv_newmortal();
     sv_setsv(TARG, TOPs);
     if (!SvREADONLY(TOPs) && SvIOK_notUV(TOPs) && !SvNOK(TOPs) && !SvPOK(TOPs)
         && SvIVX(TOPs) != IV_MAX)
@@ -921,6 +923,8 @@ PP(pp_postdec)
     dVAR; dSP; dTARGET;
     if (SvTYPE(TOPs) >= SVt_PVAV || isGV_with_GP(TOPs))
        Perl_croak_no_modify(aTHX);
+    if (SvROK(TOPs))
+       TARG = sv_newmortal();
     sv_setsv(TARG, TOPs);
     if (!SvREADONLY(TOPs) && SvIOK_notUV(TOPs) && !SvNOK(TOPs) && !SvPOK(TOPs)
         && SvIVX(TOPs) != IV_MIN)
index 99123c7..8cbc63b 100644 (file)
@@ -2,7 +2,7 @@
 
 # use strict;
 
-print "1..54\n";
+print "1..56\n";
 
 my $test = 1;
 
@@ -281,3 +281,19 @@ ok (scalar eval { my $pvbm = PVBM; $pvbm-- });
 ok (scalar eval { my $pvbm = PVBM; ++$pvbm });
 ok (scalar eval { my $pvbm = PVBM; --$pvbm });
 
+# #9466
+
+# don't use pad TARG when the thing you're copying is a ref, or the referent
+# won't get freed.
+{
+    package P9466;
+    my $x;
+    sub DESTROY { $x = 1 }
+    for (0..1) {
+       $x = 0;
+       my $a = bless {};
+       my $b = $_ ? $a++ : $a--;
+       undef $a; undef $b;
+       ::ok ($x, $x, "9466 case $_");
+    }
+}