summaryrefslogtreecommitdiff
path: root/gv.c
diff options
context:
space:
mode:
authorNicholas Clark <nick@ccl4.org>2007-10-22 20:19:55 +0000
committerNicholas Clark <nick@ccl4.org>2007-10-22 20:19:55 +0000
commit5e0caaeb4056614af54deb646e72147bdc6dcadc (patch)
treef476be90242200e3c52a92571e7f09e35f57c3f0 /gv.c
parent6b632b43d96dfd9dcd6e2f49660098045e8d0b98 (diff)
downloadperl-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.c12
1 files changed, 10 insertions, 2 deletions
diff --git a/gv.c b/gv.c
index 23c4e9f1c8..9ab582d38d 100644
--- a/gv.c
+++ b/gv.c
@@ -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 ) ) )