FAKE typeglobs seriously busted (with patch)
Perl 5 Porters [Sun, 1 Sep 1996 22:02:06 +0000 (22:02 +0000)]
Handling of fake typeglobs (scalars that are really globs
in disguise) is seriously busted since 5.002 (it wasn't
so in 5.001n).
The problem is that mg_get() on a glob calls gv_efullname()
which might coerce its first arg to a string.

Sub-critical patch to conceivably fix some %SIG problems. (Shared hash key
weren't being properly detected by some of the sig magic, but as shared
hash keys wouldn't normally be used in %SIG it's unlikely this is a
significant problem.)

This patch changes neither behavior nor performance.  However, it does
reduce code size and improve maintainability by combining some common
code in gv_fullname() and gv_efullname().

mg.c

diff --git a/mg.c b/mg.c
index b1d5415..42a0b10 100644 (file)
--- a/mg.c
+++ b/mg.c
@@ -663,7 +663,7 @@ MAGIC* mg;
 {
     I32 i;
     /* Are we fetching a signal entry? */
-    i = whichsig(mg->mg_ptr);
+    i = whichsig((mg->mg_len == HEf_SVKEY) ? SvPV((SV*)mg->mg_ptr, na) : mg->mg_ptr);
     if (i) {
        if(psig_ptr[i])
            sv_setsv(sv,psig_ptr[i]);
@@ -693,7 +693,7 @@ MAGIC* mg;
 {
     I32 i;
     /* Are we clearing a signal entry? */
-    i = whichsig(mg->mg_ptr);
+    i = whichsig((mg->mg_len == HEf_SVKEY) ? SvPV((SV*)mg->mg_ptr, na) : mg->mg_ptr);
     if (i) {
        if(psig_ptr[i]) {
            SvREFCNT_dec(psig_ptr[i]);
@@ -744,7 +744,7 @@ MAGIC* mg;
        psig_ptr[i] = SvREFCNT_inc(sv);
        if(psig_name[i])
            SvREFCNT_dec(psig_name[i]);
-       psig_name[i] = newSVpv(mg->mg_ptr,strlen(mg->mg_ptr));
+       psig_name[i] = newSVpv(s,strlen(s));
        SvTEMP_off(sv); /* Make sure it doesn't go away on us */
        SvREADONLY_on(psig_name[i]);
     }
@@ -1030,7 +1030,13 @@ magic_getglob(sv,mg)
 SV* sv;
 MAGIC* mg;
 {
-    gv_efullname(sv,((GV*)sv));/* a gv value, be nice */
+    if (SvFAKE(sv)) {                  /* FAKE globs can get coerced */
+       SvFAKE_off(sv);
+       gv_efullname(sv,((GV*)sv), "*");
+       SvFAKE_on(sv);
+    }
+    else
+       gv_efullname(sv,((GV*)sv), "*");        /* a gv value, be nice */
     return 0;
 }