summaryrefslogtreecommitdiff
path: root/hv.c
diff options
context:
space:
mode:
authorDavid Mitchell <davem@iabyn.com>2011-05-11 16:17:08 +0100
committerDavid Mitchell <davem@iabyn.com>2011-05-19 14:49:44 +0100
commit00a1a6438090b41d961c8127cc4e10d84fa70977 (patch)
treeb853ea33ce4383f808a8002b90f14b1e865c7d73 /hv.c
parent9c80917f6e6fa3fccba3eea4e7014931b5fa5233 (diff)
downloadperl-00a1a6438090b41d961c8127cc4e10d84fa70977.tar.gz
ensure hash iterator gets deleted
The recent commits to make sv_clear() iterative when freeing a hash, introduced a bug. If the hash only has one key, and that becomes the iterator, and is then deleted; then when the hash is freed, the LAZYDEL feature is skipped, and the iterated hash value fails to get deleted. The fix is simple: check for LAZYDEL before return is keys == 0.
Diffstat (limited to 'hv.c')
-rw-r--r--hv.c9
1 files changed, 3 insertions, 6 deletions
diff --git a/hv.c b/hv.c
index 3bd3e6e893..785a3066e0 100644
--- a/hv.c
+++ b/hv.c
@@ -1651,9 +1651,6 @@ S_hfreeentries(pTHX_ HV *hv)
PERL_ARGS_ASSERT_HFREEENTRIES;
- if (!((XPVHV*)SvANY(hv))->xhv_keys)
- return;
-
while ( ((sv = Perl_hfree_next_entry(aTHX_ hv, &index))) ) {
SvREFCNT_dec(sv);
}
@@ -1679,9 +1676,6 @@ Perl_hfree_next_entry(pTHX_ HV *hv, STRLEN *indexp)
PERL_ARGS_ASSERT_HFREE_NEXT_ENTRY;
- if (!((XPVHV*)SvANY(hv))->xhv_keys)
- return NULL;
-
if (SvOOK(hv) && ((iter = HvAUX(hv)))
&& ((entry = iter->xhv_eiter)) )
{
@@ -1697,6 +1691,9 @@ Perl_hfree_next_entry(pTHX_ HV *hv, STRLEN *indexp)
iter->xhv_eiter = NULL; /* HvEITER(hv) = NULL */
}
+ if (!((XPVHV*)SvANY(hv))->xhv_keys)
+ return NULL;
+
array = HvARRAY(hv);
assert(array);
while ( ! ((entry = array[*indexp])) ) {