[perl #30258] utf8 POPSTACK crash on split execution
Dave Mitchell [Fri, 2 Jul 2004 01:49:11 +0000 (01:49 +0000)]
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

pp.c
scope.c
scope.h

diff --git a/pp.c b/pp.c
index 001b9be..9425bca 100644 (file)
--- 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 (file)
--- 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 (file)
--- 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))