Re: [perl #20933] \substr reuses lvalues (sometimes)
Hugo van der Sanden [Sat, 15 Feb 2003 06:27:07 +0000 (06:27 +0000)]
From: Dave Mitchell <davem@fdgroup.com>
Date: Fri, 14 Feb 2003 22:48:27 +0000
Message-ID: <20030214224827.B6783@fdgroup.com>

with tests:
From: Slaven Rezic <slaven@rezic.de>
Date: 14 Feb 2003 20:23:20 +0100
Message-ID: <87bs1e4qfr.fsf@vran.herceg.de>

p4raw-id: //depot/perl@18705

pp.c
t/op/substr.t
t/op/vec.t

diff --git a/pp.c b/pp.c
index 67fe7f6..4fbcad4 100644 (file)
--- a/pp.c
+++ b/pp.c
@@ -3094,6 +3094,8 @@ PP(pp_substr)
                    sv_setpvn(sv,"",0); /* avoid lexical reincarnation */
            }
 
+           if (SvREFCNT(TARG) > 1)     /* don't share the TARG (#20933) */
+               TARG = sv_newmortal();
            if (SvTYPE(TARG) < SVt_PVLV) {
                sv_upgrade(TARG, SVt_PVLV);
                sv_magic(TARG, Nullsv, PERL_MAGIC_substr, Nullch, 0);
@@ -3124,6 +3126,8 @@ PP(pp_vec)
 
     SvTAINTED_off(TARG);               /* decontaminate */
     if (lvalue) {                      /* it's an lvalue! */
+       if (SvREFCNT(TARG) > 1) /* don't share the TARG (#20933) */
+           TARG = sv_newmortal();
        if (SvTYPE(TARG) < SVt_PVLV) {
            sv_upgrade(TARG, SVt_PVLV);
            sv_magic(TARG, Nullsv, PERL_MAGIC_vec, Nullch, 0);
index 85574d5..17f86e3 100755 (executable)
@@ -1,6 +1,6 @@
 #!./perl
 
-print "1..174\n";
+print "1..175\n";
 
 #P = start of string  Q = start of substr  R = end of substr  S = end of string
 
@@ -585,3 +585,10 @@ ok 173, $x eq "\xFFb\x{100}\x{200}";
 substr($x = "\x{100}\x{200}", 2, 0, "\xFFb");
 ok 174, $x eq "\x{100}\x{200}\xFFb";
 
+# [perl #20933]
+{ 
+    my $s = "ab";
+    my @r; 
+    $r[$_] = \ substr $s, $_, 1 for (0, 1);
+    ok 175, join("", map { $$_ } @r) eq "ab";
+}
index 67d7527..158711f 100755 (executable)
@@ -1,6 +1,6 @@
 #!./perl
 
-print "1..30\n";
+print "1..31\n";
 
 my $Is_EBCDIC = (ord('A') == 193) ? 1 : 0;
 
@@ -86,3 +86,14 @@ print "ok 29\n";
 vec(substr($foo, 1,3), 5, 4) = 3;
 print "not " if $foo ne "\x61\x62\x63\x34\x65\x66";
 print "ok 30\n";
+
+# A variation of [perl #20933]
+{
+    my $s = "";
+    vec($s, 0, 1) = 0;
+    vec($s, 1, 1) = 1;
+    my @r;
+    $r[$_] = \ vec $s, $_, 1 for (0, 1);
+    print "not " if (${ $r[0] } != 0 || ${ $r[1] } != 1);
+    print "ok 31\n";
+}