Blob Blame History Raw
From 2c639acf40b4abc2783352f8e20dbfb68389e633 Mon Sep 17 00:00:00 2001
From: David Mitchell <davem@iabyn.com>
Date: Mon, 28 Nov 2016 08:03:49 +0000
Subject: [PATCH] crash on explicit return from s///e
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit

Petr Pisar: Ported to 5.24.0:

commit 7332835e5da7b7a793ef814a84e53003be1d0138
Author: David Mitchell <davem@iabyn.com>
Date:   Mon Nov 28 08:03:49 2016 +0000

    crash on explicit return from s///e

    RT #130188

    In

        sub f {
            my $x = 'a';
            $x =~ s/./return;/e;
        }

    the 'return' triggers popping any contexts above the subroutine context:
    in this case, a CXt_SUBST context. In this case, Perl_dounwind() calls
    cx_popblock() for the bottom-most popped context, to restore any saved
    vars. However, CXt_SUBST is the one context type which *doesn't* use
    'struct block' as part of its context struct union, so you can't
    cx_popblock() a CXt_SUBST context.

    This commit makes it skip the cx_popblock() in this case.

    Bug was introduced by me with v5.23.7-235-gfc6e609.

Signed-off-by: Petr Písař <ppisar@redhat.com>
---
 pp_ctl.c     |  6 ++++++
 t/re/subst.t | 17 ++++++++++++++++-
 2 files changed, 22 insertions(+), 1 deletion(-)

diff --git a/pp_ctl.c b/pp_ctl.c
index 99ff59a..b94c09a 100644
--- a/pp_ctl.c
+++ b/pp_ctl.c
@@ -1529,6 +1529,12 @@ Perl_dounwind(pTHX_ I32 cxix)
 	switch (CxTYPE(cx)) {
 	case CXt_SUBST:
 	    CX_POPSUBST(cx);
+            /* CXt_SUBST is not a block context type, so skip the
+             * cx_popblock(cx) below */
+            if (cxstack_ix == cxix + 1) {
+                cxstack_ix--;
+                return;
+            }
 	    break;
 	case CXt_SUB:
 	    cx_popsub(cx);
diff --git a/t/re/subst.t b/t/re/subst.t
index 26a78c7..c039cc4 100644
--- a/t/re/subst.t
+++ b/t/re/subst.t
@@ -11,7 +11,7 @@ BEGIN {
     require './loc_tools.pl';
 }
 
-plan( tests => 271 );
+plan( tests => 272 );
 
 $_ = 'david';
 $a = s/david/rules/r;
@@ -1119,3 +1119,15 @@ SKIP: {
                    {stderr => 1 },
                    '[perl #129038 ] s/\xff//l no longer crashes');
 }
+
+# [perl #130188] crash on return from substitution in subroutine
+# make sure returning from s///e doesn't SEGV
+{
+    my $f = sub {
+        my $x = 'a';
+        $x =~ s/./return;/e;
+    };
+    my $x = $f->();
+    pass("RT #130188");
+}
+
+
+
+
-- 
2.7.4