From: Dave Mitchell <davem@fdisolutions.com>
Date: Fri, 2 Jul 2004 01:49:11 +0000 (+0000)
Subject: [perl #30258] utf8 POPSTACK crash on split execution
X-Git-Url: http://git.shadowcat.co.uk/gitweb/gitweb.cgi?a=commitdiff_plain;h=8b7059b1a993d7ac934442e99623d9dbc5fe3ce8;p=p5sagit%2Fp5-mst-13.2.git

[perl #30258] utf8 POPSTACK crash on split execution
split() does a SWITCHSTACK to directly split to an array, but
if it subsequently dies (eg the regex triggers a 'use utf8' which
is then denied by Safe), then the switch doesn't get undone. Add
a new save type to allow for this.

p4raw-id: //depot/perl@23023
---

diff --git a/pp.c b/pp.c
index 001b9be..9425bca 100644
--- a/pp.c
+++ b/pp.c
@@ -4439,7 +4439,6 @@ PP(pp_split)
     I32 origlimit = limit;
     I32 realarray = 0;
     I32 base;
-    AV *oldstack = PL_curstack;
     I32 gimme = GIMME_V;
     I32 oldsave = PL_savestack_ix;
     I32 make_mortal = 1;
@@ -4488,8 +4487,7 @@ PP(pp_split)
 		    AvARRAY(ary)[i] = &PL_sv_undef;	/* don't free mere refs */
 	    }
 	    /* temporarily switch stacks */
-	    SWITCHSTACK(PL_curstack, ary);
-	    PL_curstackinfo->si_stack = ary;
+	    SAVESWITCHSTACK(PL_curstack, ary);
 	    make_mortal = 0;
 	}
     }
@@ -4658,7 +4656,6 @@ PP(pp_split)
 	}
     }
 
-    LEAVE_SCOPE(oldsave);
     iters = (SP - PL_stack_base) - base;
     if (iters > maxiters)
 	DIE(aTHX_ "Split loop");
@@ -4684,10 +4681,11 @@ PP(pp_split)
 	}
     }
 
+    PUTBACK;
+    LEAVE_SCOPE(oldsave); /* may undo an earlier SWITCHSTACK */
+    SPAGAIN;
     if (realarray) {
 	if (!mg) {
-	    SWITCHSTACK(ary, oldstack);
-	    PL_curstackinfo->si_stack = oldstack;
 	    if (SvSMAGICAL(ary)) {
 		PUTBACK;
 		mg_set((SV*)ary);
diff --git a/scope.c b/scope.c
index 452ea77..54d4488 100644
--- a/scope.c
+++ b/scope.c
@@ -1063,6 +1063,15 @@ Perl_leave_scope(pTHX_ I32 base)
 		    AvARRAY((PAD*)ptr)[off] = (SV*)SSPOPPTR;
 	    }
 	    break;
+	case SAVEt_SAVESWITCHSTACK:
+	    {
+		dSP;
+		AV* t = (AV*)SSPOPPTR;
+		AV* f = (AV*)SSPOPPTR;
+		SWITCHSTACK(t,f);
+		PL_curstackinfo->si_stack = f;
+	    }
+	    break;
 	case SAVEt_SET_SVFLAGS:
 	    {
 		U32 val  = (U32)SSPOPINT;
diff --git a/scope.h b/scope.h
index bbb5562..f86039d 100644
--- a/scope.h
+++ b/scope.h
@@ -48,6 +48,7 @@
 #define SAVEt_SHARED_PVREF	37
 #define SAVEt_BOOL		38
 #define SAVEt_SET_SVFLAGS	39
+#define SAVEt_SAVESWITCHSTACK	40
 
 #ifndef SCOPE_SAVES_SIGNAL_MASK
 #define SCOPE_SAVES_SIGNAL_MASK 0
@@ -169,6 +170,16 @@ Closing bracket on a callback.  See C<ENTER> and L<perlcall>.
 	SSPUSHINT(SAVEt_COMPPAD);				\
     } STMT_END
 
+#define SAVESWITCHSTACK(f,t) \
+    STMT_START {					\
+	SSCHECK(3);					\
+	SSPUSHPTR((SV*)(f));				\
+	SSPUSHPTR((SV*)(t));				\
+	SSPUSHINT(SAVEt_SAVESWITCHSTACK);		\
+	SWITCHSTACK((f),(t));				\
+	PL_curstackinfo->si_stack = (t);		\
+    } STMT_END
+
 #ifdef USE_ITHREADS
 #  define SAVECOPSTASH(c)	SAVEPPTR(CopSTASHPV(c))
 #  define SAVECOPSTASH_FREE(c)	SAVESHAREDPV(CopSTASHPV(c))