This is a live mirror of the Perl 5 development currently hosted at https://github.com/perl/perl5
Stop hash assignment from leaking on croak
authorFather Chrysostomos <sprout@cpan.org>
Sat, 22 Sep 2012 14:12:04 +0000 (07:12 -0700)
committerFather Chrysostomos <sprout@cpan.org>
Sun, 23 Sep 2012 00:10:43 +0000 (17:10 -0700)
pp_hot.c
t/op/svleak.t

index 827395f..6057614 100644 (file)
--- a/pp_hot.c
+++ b/pp_hot.c
@@ -1013,7 +1013,7 @@ PP(pp_aassign)
                    HE *didstore;
                    sv = *relem ? *relem : &PL_sv_no;
                    relem++;
-                   tmpstr = newSV(0);
+                   tmpstr = sv_newmortal();
                    if (*relem)
                        sv_setsv(tmpstr,*relem);        /* value */
                    relem++;
@@ -1030,11 +1030,10 @@ PP(pp_aassign)
                        }
                    }
                    didstore = hv_store_ent(hash,sv,tmpstr,0);
+                   if (didstore) SvREFCNT_inc_simple_void_NN(tmpstr);
                    if (magic) {
                        if (SvSMAGICAL(tmpstr))
                            mg_set(tmpstr);
-                       if (!didstore)
-                           sv_2mortal(tmpstr);
                    }
                    TAINT_NOT;
                }
index 2323615..6ed0408 100644 (file)
@@ -15,7 +15,7 @@ BEGIN {
 
 use Config;
 
-plan tests => 29;
+plan tests => 30;
 
 # 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
@@ -199,3 +199,16 @@ leak(2, 0, sub {
     each %$h;
     undef $h;
 }, 'tied hash iteration does not leak');
+
+# Hash assignment was leaking when assigning explosive scalars
+package sty {
+    sub TIESCALAR { bless [] }
+    sub FETCH    { die }
+}
+leak(2, 0, sub {
+    tie my $x, sty;
+    eval {%a = ($x, 0)}; # key
+    eval {%a = (0, $x)}; # value
+    eval {%a = ($x,$x)}; # both
+}, 'hash assignment does not leak');
+