diff options
-rw-r--r-- | hv.c | 3 | ||||
-rw-r--r-- | t/op/svleak.t | 15 |
2 files changed, 17 insertions, 1 deletions
@@ -2370,6 +2370,7 @@ Perl_hv_iternext_flags(pTHX_ HV *hv, I32 flags) if (entry) { sv_setsv(key, HeSVKEY_force(entry)); SvREFCNT_dec(HeSVKEY(entry)); /* get rid of previous key */ + HeSVKEY_set(entry, NULL); } else { char *k; @@ -2377,6 +2378,7 @@ Perl_hv_iternext_flags(pTHX_ HV *hv, I32 flags) /* one HE per MAGICAL hash */ iter->xhv_eiter = entry = new_HE(); /* HvEITER(hv) = new_HE() */ + HvLAZYDEL_on(hv); /* make sure entry gets freed */ Zero(entry, 1, HE); Newxz(k, HEK_BASESIZE + sizeof(const SV *), char); hek = (HEK*)k; @@ -2393,6 +2395,7 @@ Perl_hv_iternext_flags(pTHX_ HV *hv, I32 flags) Safefree(HeKEY_hek(entry)); del_HE(entry); iter->xhv_eiter = NULL; /* HvEITER(hv) = NULL */ + HvLAZYDEL_off(hv); return NULL; } } diff --git a/t/op/svleak.t b/t/op/svleak.t index e6636b84c0..2323615c03 100644 --- a/t/op/svleak.t +++ b/t/op/svleak.t @@ -15,7 +15,7 @@ BEGIN { use Config; -plan tests => 28; +plan tests => 29; # 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 @@ -186,3 +186,16 @@ SKIP: { # [perl #114764] Attributes leak scalars leak(2, 0, sub { eval 'my $x : shared' }, 'my $x :shared used to leak'); + +# Tied hash iteration was leaking if the hash was freed before itera- +# tion was over. +package t { + sub TIEHASH { bless [] } + sub FIRSTKEY { 0 } +} +leak(2, 0, sub { + my $h = {}; + tie %$h, t; + each %$h; + undef $h; +}, 'tied hash iteration does not leak'); |