summaryrefslogtreecommitdiff
path: root/gv.c
diff options
context:
space:
mode:
authorFather Chrysostomos <sprout@cpan.org>2011-04-06 22:44:28 -0700
committerFather Chrysostomos <sprout@cpan.org>2011-04-06 22:44:28 -0700
commit1a063a891daa888a733d9623fd6d707de87c6bd9 (patch)
tree0f388ab5059d7d3ea6f1a49d08ca1f7209f00866 /gv.c
parent837c87981b0d72533fc9e43f83cca13e78853569 (diff)
downloadperl-1a063a891daa888a733d9623fd6d707de87c6bd9.tar.gz
[perl #87388] bless[], "main::" crashes
As mention in the ticket, this was caused by b4dd662, which removed ‘dead’ code from gv_stashpvn: commit b4dd66232df8f0d1c00796970dec7fc37fbe9edf Author: Nicholas Clark <nick@ccl4.org> Date: Fri Oct 8 21:33:29 2010 +0100 Remove dead code from Perl_gv_stashpvn(). GvHV() and HvNAME() will both always already be set, as gv_fetchpvn_flags() will initialise these as it walks the string in its initial loop to locate the correct stash, then return early because name == name_end. This code has been dead since it was added in 5.000. --- a/gv.c +++ b/gv.c @@ -927,11 +927,9 @@ Perl_gv_stashpvn(pTHX_ const char *name, U32 namelen, I32 flags) Safefree(tmpbuf); if (!tmpgv) return NULL; - if (!GvHV(tmpgv)) - GvHV(tmpgv) = newHV(); stash = GvHV(tmpgv); - if (!HvNAME_get(stash)) - hv_name_set(stash, name, namelen, 0); + assert(stash); + assert(HvNAME_get(stash)); return stash; } This routine, before the snippet shown, adds two colons to the end of the name and then passes "main::::" to gv_fetch_pvn_flags. gv_fetch_pvn_flags, when it parses a "::", sets the next subname to point to the character after the second colon, and then continues scanning from the next character *after* that. So foo::::bar becomes $foo::{"::bar"} and main:::: becomes $main::{"::"}. The code that assigns the name to the stash and the early exit are both inside an if(we have a package separator) block, but the final :: is not considered one, so a nameless hash is returned. The easiest way to fix this is to revert just the changes to lines that deal with the name (since the other deleted lines are really dead).
Diffstat (limited to 'gv.c')
-rw-r--r--gv.c3
1 files changed, 2 insertions, 1 deletions
diff --git a/gv.c b/gv.c
index 96301ff151..b1bc60f4e6 100644
--- a/gv.c
+++ b/gv.c
@@ -959,8 +959,9 @@ Perl_gv_stashpvn(pTHX_ const char *name, U32 namelen, I32 flags)
if (!tmpgv)
return NULL;
stash = GvHV(tmpgv);
+ if (!HvNAME_get(stash))
+ hv_name_set(stash, name, namelen, 0);
assert(stash);
- assert(HvNAME_get(stash));
return stash;
}