diff options
author | Father Chrysostomos <sprout@cpan.org> | 2012-01-09 22:18:56 -0800 |
---|---|---|
committer | Father Chrysostomos <sprout@cpan.org> | 2012-01-09 22:18:56 -0800 |
commit | 8505eec04db975056f12e93f306696ee3bf089ad (patch) | |
tree | 193c6e43b34dda8501bd203afe08340030ec96ae /hv.c | |
parent | 2537c17b0fdedb3e9b4301852ab5f7e7d6e38f19 (diff) | |
download | perl-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.
Diffstat (limited to 'hv.c')
-rw-r--r-- | hv.c | 17 |
1 files changed, 9 insertions, 8 deletions
@@ -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; } /* |