[perl #56908] DBI memory leak in 5.10.0 due to change 26530
Dave Mitchell [Wed, 20 Aug 2008 23:15:36 +0000 (23:15 +0000)]
A weakref to a HV would leak, because the xhv_backreferences
array is created with a refcount of 2 (to avoid premature freeing
during global destruction), but the RC was only decremented once
when the parent HV was freed.
Also, when thread cloned, the new array was being created with a
RC of 1, rather than 2, which coincidentally worked due to the
first bug.

p4raw-id: //depot/perl@34209

hv.c
sv.c

diff --git a/hv.c b/hv.c
index 3d4d3af..24d9150 100644 (file)
--- a/hv.c
+++ b/hv.c
@@ -1985,6 +1985,7 @@ Perl_hv_kill_backrefs(pTHX_ HV *hv) {
     if (av) {
        HvAUX(hv)->xhv_backreferences = 0;
        Perl_sv_kill_backrefs(aTHX_ (SV*) hv, av);
+       SvREFCNT_dec(av);
     }
 }
 
diff --git a/sv.c b/sv.c
index 04d6e43..4792ad1 100644 (file)
--- a/sv.c
+++ b/sv.c
@@ -10784,10 +10784,11 @@ Perl_sv_dup(pTHX_ const SV *const sstr, CLONE_PARAMS *const param)
                        daux->xhv_eiter = saux->xhv_eiter
                            ? he_dup(saux->xhv_eiter,
                                        (bool)!!HvSHAREKEYS(sstr), param) : 0;
+                       /* backref array needs refcnt=2; see sv_add_backref */
                        daux->xhv_backreferences =
                            saux->xhv_backreferences
                                ? (AV*) SvREFCNT_inc(
-                                       sv_dup((SV*)saux->xhv_backreferences, param))
+                                       sv_dup_inc((SV*)saux->xhv_backreferences, param))
                                : 0;
 
                         daux->xhv_mro_meta = saux->xhv_mro_meta