diff options
author | Father Chrysostomos <sprout@cpan.org> | 2010-10-29 20:45:34 -0700 |
---|---|---|
committer | Father Chrysostomos <sprout@cpan.org> | 2010-10-29 21:50:24 -0700 |
commit | 00169e2cdde29138824a7bf6b66d5875aaa8278d (patch) | |
tree | aeb3b50ba3698ec9d26053d42e414fda70a983ba /hv.c | |
parent | bc56db2a697ebe59892fabdcfa5aa910ed4f2885 (diff) | |
download | perl-00169e2cdde29138824a7bf6b66d5875aaa8278d.tar.gz |
Switch the core MRO code over to HvENAME
This has the side-effect of fixing these one-liners:
$ perl5.13.5 -le' my $glob = \*foo::ISA; delete $::{"foo::"}; *$glob = *a'
Bus error
$ perl5.13.5 -le' my $glob = \*foo::ISA; delete $::{"foo::"}; *$glob = []'
Bus error
$ perl5.13.6 -le'sub baz; my $glob = \*foo::bar; delete $::{"foo::"}; *$glob = *baz;'
Bus error
$ perl5.13.6 -le'sub foo::bar; my $glob = \*foo::bar; delete $::{"foo::"}; *$glob = *baz;'
Bus error
In the first two cases the crash was inadvertently fixed (isn’t it
nice when that happens?) in 5.13.6 (by 6f86b615fa7), but there was
still a fatal error:
Can't call mro_isa_changed_in() on anonymous symbol table at -e line 1.
Because sv_clear calls ->DESTROY, if an object’s stash has been
detached from the symbol table, mro_get_linear_isa can be called on a
hash with no HvENAME. So HvNAME is used as a fallback for those cases.
Diffstat (limited to 'hv.c')
-rw-r--r-- | hv.c | 8 |
1 files changed, 4 insertions, 4 deletions
@@ -1481,7 +1481,7 @@ Perl_hv_free_ent(pTHX_ HV *hv, register HE *entry) if (!entry) return; val = HeVAL(entry); - if (val && isGV(val) && isGV_with_GP(val) && GvCVu(val) && HvNAME_get(hv)) + if (val && isGV(val) && isGV_with_GP(val) && GvCVu(val) && HvENAME(hv)) mro_method_changed_in(hv); /* deletion of method from stash */ SvREFCNT_dec(val); if (HeKLEN(entry) == HEf_SVKEY) { @@ -1568,7 +1568,7 @@ Perl_hv_clear(pTHX_ HV *hv) HvREHASH_off(hv); reset: if (SvOOK(hv)) { - if(HvNAME_get(hv)) + if(HvENAME_get(hv)) mro_isa_changed_in(hv); HvEITER_set(hv, NULL); } @@ -1852,11 +1852,11 @@ Perl_hv_undef(pTHX_ HV *hv) DEBUG_A(Perl_hv_assert(aTHX_ hv)); xhv = (XPVHV*)SvANY(hv); - if ((name = HvNAME_get(hv)) && !PL_dirty) + if ((name = HvENAME_get(hv)) && !PL_dirty) mro_isa_changed_in(hv); hfreeentries(hv); - if (name) { + if (name || (name = HvNAME(hv))) { if (PL_stashcache) (void)hv_delete(PL_stashcache, name, HvNAMELEN_get(hv), G_DISCARD); hv_name_set(hv, NULL, 0, 0); |