diff options
author | Nicholas Clark <nick@ccl4.org> | 2007-10-22 20:19:55 +0000 |
---|---|---|
committer | Nicholas Clark <nick@ccl4.org> | 2007-10-22 20:19:55 +0000 |
commit | 5e0caaeb4056614af54deb646e72147bdc6dcadc (patch) | |
tree | f476be90242200e3c52a92571e7f09e35f57c3f0 /gv.c | |
parent | 6b632b43d96dfd9dcd6e2f49660098045e8d0b98 (diff) | |
download | perl-5e0caaeb4056614af54deb646e72147bdc6dcadc.tar.gz |
SQL::Translator triggered a subtle piece of wrongness, whereby it
managed to cause a proxy constant subroutine in the symbol table to
be upgraded to a GV at precisely the point where it was being
considered as a possible IO handle name. The core's user-space visible
behaviour certainly was buggy - I believe this patch to be the correct
fix. However, it seems to be very hard to write a test for it.
p4raw-id: //depot/perl@32172
Diffstat (limited to 'gv.c')
-rw-r--r-- | gv.c | 12 |
1 files changed, 10 insertions, 2 deletions
@@ -875,6 +875,7 @@ Perl_gv_fetchpvn_flags(pTHX_ const char *nambeg, STRLEN full_len, I32 flags, const I32 add = flags & ~GV_NOADD_MASK; const char *const name_end = nambeg + full_len; const char *const name_em1 = name_end - 1; + U32 faking_it; if (flags & GV_NOTQUAL) { /* Caller promised that there is no stash, so we can skip the check. */ @@ -1071,12 +1072,19 @@ Perl_gv_fetchpvn_flags(pTHX_ const char *nambeg, STRLEN full_len, I32 flags, return gv; } - /* Adding a new symbol */ + /* Adding a new symbol. + Unless of course there was already something non-GV here, in which case + we want to behave as if there was always a GV here, containing some sort + of subroutine. + Otherwise we run the risk of creating things like GvIO, which can cause + subtle bugs. eg the one that tripped up SQL::Translator */ + + faking_it = SvOK(gv); if (add & GV_ADDWARN && ckWARN_d(WARN_INTERNAL)) Perl_warner(aTHX_ packWARN(WARN_INTERNAL), "Had to create %s unexpectedly", nambeg); gv_init(gv, stash, name, len, add & GV_ADDMULTI); - gv_init_sv(gv, sv_type); + gv_init_sv(gv, faking_it ? SVt_PVCV : sv_type); if (isALPHA(name[0]) && ! (isLEXWARN_on ? ckWARN(WARN_ONCE) : (PL_dowarn & G_WARN_ON ) ) ) |