summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorFather Chrysostomos <sprout@cpan.org>2012-01-09 22:18:56 -0800
committerFather Chrysostomos <sprout@cpan.org>2012-01-09 22:18:56 -0800
commit8505eec04db975056f12e93f306696ee3bf089ad (patch)
tree193c6e43b34dda8501bd203afe08340030ec96ae
parent2537c17b0fdedb3e9b4301852ab5f7e7d6e38f19 (diff)
downloadperl-8505eec04db975056f12e93f306696ee3bf089ad.tar.gz
Fix crash in hv_undef
Commit 60edcf09a was supposed to make things less buggy, but putting the ENTER/LEAVE in h_freeentries was a mistake, as both hv_undef and hv_clear still access the hv after calling h_freeentries. Why it didn’t crash for me is anyone’s guess.
-rw-r--r--hv.c17
1 files changed, 9 insertions, 8 deletions
diff --git a/hv.c b/hv.c
index baeeae711f..f166968195 100644
--- a/hv.c
+++ b/hv.c
@@ -1566,6 +1566,8 @@ Perl_hv_clear(pTHX_ HV *hv)
xhv = (XPVHV*)SvANY(hv);
+ ENTER;
+ SAVEFREESV(SvREFCNT_inc_simple_NN(hv));
if (SvREADONLY(hv) && HvARRAY(hv) != NULL) {
/* restricted hash: convert all keys to placeholders */
STRLEN i;
@@ -1603,6 +1605,7 @@ Perl_hv_clear(pTHX_ HV *hv)
mro_isa_changed_in(hv);
HvEITER_set(hv, NULL);
}
+ LEAVE;
}
/*
@@ -1684,20 +1687,12 @@ S_hfreeentries(pTHX_ HV *hv)
STRLEN index = 0;
XPVHV * const xhv = (XPVHV*)SvANY(hv);
SV *sv;
- const bool save = !!SvREFCNT(hv);
PERL_ARGS_ASSERT_HFREEENTRIES;
- if (save) {
- ENTER;
- SAVEFREESV(SvREFCNT_inc_simple_NN(hv));
- }
-
while ((sv = Perl_hfree_next_entry(aTHX_ hv, &index))||xhv->xhv_keys) {
SvREFCNT_dec(sv);
}
-
- if (save) LEAVE;
}
@@ -1790,6 +1785,7 @@ Perl_hv_undef_flags(pTHX_ HV *hv, U32 flags)
dVAR;
register XPVHV* xhv;
const char *name;
+ const bool save = !!SvREFCNT(hv);
if (!hv)
return;
@@ -1814,6 +1810,10 @@ Perl_hv_undef_flags(pTHX_ HV *hv, U32 flags)
);
hv_name_set(hv, NULL, 0, 0);
}
+ if (save) {
+ ENTER;
+ SAVEFREESV(SvREFCNT_inc_simple_NN(hv));
+ }
hfreeentries(hv);
if (SvOOK(hv)) {
struct xpvhv_aux * const aux = HvAUX(hv);
@@ -1867,6 +1867,7 @@ Perl_hv_undef_flags(pTHX_ HV *hv, U32 flags)
if (SvRMAGICAL(hv))
mg_clear(MUTABLE_SV(hv));
+ if (save) LEAVE;
}
/*