summaryrefslogtreecommitdiff
path: root/hv.c
diff options
context:
space:
mode:
authorFather Chrysostomos <sprout@cpan.org>2011-04-15 22:33:31 -0700
committerFather Chrysostomos <sprout@cpan.org>2011-04-15 22:34:16 -0700
commit1f656fcf060e343780f7a91a2ce567e8a9de9414 (patch)
tree1c24080e8393811be538f104daae330cdb966498 /hv.c
parent2f81e8f3910ca00e129de843e034fb70a0bcc905 (diff)
downloadperl-1f656fcf060e343780f7a91a2ce567e8a9de9414.tar.gz
Followup to 088225f/[perl #88132]: packages ending with :
Commit 088225f was not sufficient to fix the regression. It still exists for packages whose names end with a single colon. I discovered this when trying to determine why RDF::Trine was crashing with 5.14-to-be. In trying to write tests for it, I ended up triggering the same crash that RDF::Trine is having, but in a different way. In the end, it was easier to fix about three or four bugs (depending on how you count them), rather than try to fix only the regression that #88132 deals with (isa caches not updating when packages ending with colons are aliased), as they are all intertwined. The changes are as follows: Concerning the if (!(flags & ~GV_NOADD_MASK)...) statement in gv_stashpvn: Normally, gv_fetchpvn_flags (which it calls and whose retval is assigned to tmpgv) returns NULL if it has not been told to add anything and if the gv requested looks like a stash gv (ends with ::). If the number of colons is odd (foo:::), that code path is bypassed, so gv_stashpvn returns a GV without a hash. So gv_stashpvn tries to used that NULL hash and crashes. It should instead return NULL, to be consistent with the two-colon case. Blindly assigning a name to a stash does not work if the stash has multiple effective names. A call to mro_package_moved is required as well. So what gv_stashpvn was doing was insufficient. The parts of the mro code that check for globs or stash elems that contain stashes by looking for :: at the end of the name now take into account that the name might consist of a single : instead.
Diffstat (limited to 'hv.c')
-rw-r--r--hv.c9
1 files changed, 7 insertions, 2 deletions
diff --git a/hv.c b/hv.c
index ed5061fb6d..56598d79fb 100644
--- a/hv.c
+++ b/hv.c
@@ -1026,7 +1026,11 @@ S_hv_delete_common(pTHX_ HV *hv, SV *keysv, const char *key, STRLEN klen,
if (HeVAL(entry) && HvENAME_get(hv)) {
gv = (GV *)HeVAL(entry);
if (keysv) key = SvPV(keysv, klen);
- if (klen > 1 && key[klen-2] == ':' && key[klen-1] == ':'
+ if ((
+ (klen > 1 && key[klen-2] == ':' && key[klen-1] == ':')
+ ||
+ (klen == 1 && key[0] == ':')
+ )
&& (klen != 6 || hv!=PL_defstash || memNE(key,"main::",6))
&& SvTYPE(gv) == SVt_PVGV && (stash = GvHV((GV *)gv))
&& HvENAME_get(stash)) {
@@ -1780,7 +1784,8 @@ S_hfreeentries(pTHX_ HV *hv)
) {
STRLEN klen;
const char * const key = HePV(oentry,klen);
- if (klen > 1 && key[klen-1]==':' && key[klen-2]==':') {
+ if ((klen > 1 && key[klen-1]==':' && key[klen-2]==':')
+ || (klen == 1 && key[0] == ':')) {
mro_package_moved(
NULL, GvHV(HeVAL(oentry)),
(GV *)HeVAL(oentry), 0