From 1f656fcf060e343780f7a91a2ce567e8a9de9414 Mon Sep 17 00:00:00 2001 From: Father Chrysostomos Date: Fri, 15 Apr 2011 22:33:31 -0700 Subject: 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. --- gv.c | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) (limited to 'gv.c') diff --git a/gv.c b/gv.c index 7741af36c9..d22a4398fb 100644 --- a/gv.c +++ b/gv.c @@ -959,8 +959,16 @@ Perl_gv_stashpvn(pTHX_ const char *name, U32 namelen, I32 flags) if (!tmpgv) return NULL; stash = GvHV(tmpgv); - if (!HvNAME_get(stash)) + if (!(flags & ~GV_NOADD_MASK) && !stash) return NULL; + if (!HvNAME_get(stash)) { hv_name_set(stash, name, namelen, 0); + + /* FIXME: This is a repeat of logic in gv_fetchpvn_flags */ + /* If the containing stash has multiple effective + names, see that this one gets them, too. */ + if (HvAUX(GvSTASH(tmpgv))->xhv_name_count) + mro_package_moved(stash, NULL, tmpgv, 1); + } assert(stash); return stash; } -- cgit v1.2.1