[PATCH] [perl #20321] Non-destructive Perl_av_make
Bo Borgerson [Mon, 2 Nov 2009 17:25:23 +0000 (11:25 -0600)]
Don't let sv_setsv swipe temps in av_make, since the source array
might have multiple references to the same temp scalar (e.g. from
a list slice).

av.c
t/op/list.t

diff --git a/av.c b/av.c
index 4718af2..a4d6ea2 100644 (file)
--- a/av.c
+++ b/av.c
@@ -404,8 +404,14 @@ Perl_av_make(pTHX_ register I32 size, register SV **strp)
        AvFILLp(av) = AvMAX(av) = size - 1;
        for (i = 0; i < size; i++) {
            assert (*strp);
+
+           /* Don't let sv_setsv swipe, since our source array might
+              have multiple references to the same temp scalar (e.g.
+              from a list slice) */
+
            ary[i] = newSV(0);
-           sv_setsv(ary[i], *strp);
+           sv_setsv_flags(ary[i], *strp,
+                          SV_GMAGIC|SV_DO_COW_SVSETSV|SV_NOSTEAL);
            strp++;
        }
     }
index a8fdc18..184724a 100644 (file)
@@ -6,7 +6,7 @@ BEGIN {
 }
 
 require "test.pl";
-plan( tests => 57 );
+plan( tests => 58 );
 
 @foo = (1, 2, 3, 4);
 cmp_ok($foo[0], '==', 1, 'first elem');
@@ -161,3 +161,7 @@ cmp_ok(join('',(1,2),3,(4,5)),'eq','12345','list (..).(..)');
     test_zero_args("do-returned list slice", do { (10,11)[2,3]; });
 }
 
+{
+    # perl #20321
+    is (join('', @{[('abc'=~/./g)[0,1,2,1,0]]}), "abcba");
+}