Don’t clobber all magic when clobbering vstring
authorFather Chrysostomos <sprout@cpan.org>
Fri, 23 Dec 2011 22:28:33 +0000 (14:28 -0800)
committerFather Chrysostomos <sprout@cpan.org>
Fri, 23 Dec 2011 22:45:55 +0000 (14:45 -0800)
This code in sv_setsv, introduced in ece467f9b3, can’t possi-
bly be right:

    if ( SvVOK(dstr) )
    {
/* need to nuke the magic */
mg_free(dstr);
    }

And here is a test to prove it:

sub TIESCALAR { bless[]}
sub STORE {}
tie $@, "";
$@ = v0;
warn tied $@; # main=ARRAY(0xc0ffee)
$@ = 3;
warn tied $@; # something’s wrong

It blows away tiedness.

You could do that to any variable.

Let’s see:

$! = v0;
$! = 3;
open foo, 'oentuhaeontu' or die $!;  # 3 at - line 3.

Youch!

Let’s just free vstring magic, shall we?

sv.c
t/op/ver.t

diff --git a/sv.c b/sv.c
index 019e8dd..39ddbff 100644 (file)
--- a/sv.c
+++ b/sv.c
@@ -3949,7 +3949,7 @@ Perl_sv_setsv_flags(pTHX_ SV *dstr, register SV* sstr, const I32 flags)
     if ( SvVOK(dstr) )
     {
        /* need to nuke the magic */
-       mg_free(dstr);
+       sv_unmagic(dstr, PERL_MAGIC_vstring);
     }
 
     /* There's a lot of redundancy below but we're going for speed here */
index f820099..fa94d5e 100644 (file)
@@ -11,7 +11,7 @@ $DOWARN = 1; # enable run-time warnings now
 
 use Config;
 
-plan( tests => 54 );
+plan( tests => 55 );
 
 eval 'use v5.5.640';
 is( $@, '', "use v5.5.640; $@");
@@ -262,6 +262,14 @@ ok( exists $h{chr(65).chr(66)}, "v-stringness is engaged for vX.Y" );
 %h = (65.66.67 => 42);
 ok( exists $h{chr(65).chr(66).chr(67)}, "v-stringness is engaged for X.Y.Z" );
 
+{
+    local $|;
+    $| = v0;
+    $| = 1;
+    --$|; --$|;
+    is $|, 1, 'clobbering vstrings does not clobber all magic';
+}
+
 
 # The following tests whether v-strings are correctly
 # interpreted by the tokeniser when it's in a XTERMORDORDOR