This is a live mirror of the Perl 5 development currently hosted at https://github.com/perl/perl5
[perl #126602] make sure targ isn't freed from under us
authorTony Cook <tony@develop-help.com>
Wed, 11 Nov 2015 00:29:03 +0000 (11:29 +1100)
committerTony Cook <tony@develop-help.com>
Mon, 16 Nov 2015 23:36:58 +0000 (10:36 +1100)
cop.h
t/re/subst.t

diff --git a/cop.h b/cop.h
index d36d189..b15ddf4 100644 (file)
--- a/cop.h
+++ b/cop.h
@@ -939,11 +939,13 @@ struct subst {
        cx->sb_rx               = rx,                                   \
        cx->cx_type             = CXt_SUBST | (once ? CXp_ONCE : 0);    \
        rxres_save(&cx->sb_rxres, rx);                                  \
-       (void)ReREFCNT_inc(rx)
+       (void)ReREFCNT_inc(rx);                                         \
+        SvREFCNT_inc_void_NN(targ)
 
 #  define POPSUBST(cx) cx = &cxstack[cxstack_ix--];                    \
        rxres_free(&cx->sb_rxres);                                      \
-       ReREFCNT_dec(cx->sb_rx)
+       ReREFCNT_dec(cx->sb_rx);                                        \
+        SvREFCNT_dec_NN(cx->sb_targ)
 #endif
 
 #define CxONCE(cx)             ((cx)->cx_type & CXp_ONCE)
index 2fed182..7939fe5 100644 (file)
@@ -9,7 +9,7 @@ BEGIN {
     require './loc_tools.pl';
 }
 
-plan( tests => 267 );
+plan( tests => 268 );
 
 $_ = 'david';
 $a = s/david/rules/r;
@@ -1078,3 +1078,8 @@ SKIP: {
     $s1 =~ s/.?/$s1++/ge;
     is($s1, "01","RT #123954 s1");
 }
+{
+    # RT #126602 double free if the value being modified is freed in the replacement
+    fresh_perl_is('s//*_=0;s|0||;00.y0/e; print qq(ok\n)', "ok\n", { stderr => 1 },
+                  "[perl #126602] s//*_=0;s|0||/e crashes");
+}