From: Dave Mitchell <davem@fdisolutions.com>
Date: Sun, 1 Apr 2007 00:51:00 +0000 (+0000)
Subject: free backtrack track when on unexpected exit, eg /(?{ die })/
X-Git-Url: http://git.shadowcat.co.uk/gitweb/gitweb.cgi?a=commitdiff_plain;h=2f554ef70d979db80efccf5fce9a84ca1a2f45dc;p=p5sagit%2Fp5-mst-13.2.git

free backtrack track when on unexpected exit, eg /(?{ die })/

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

diff --git a/regexec.c b/regexec.c
index 470f251..c65c33b 100644
--- a/regexec.c
+++ b/regexec.c
@@ -2592,6 +2592,26 @@ S_reg_check_named_buff_matched(pTHX_ const regexp *rex, const regnode *scan) {
     return 0;
 }
 
+
+/* free all slabs above current one  - called during LEAVE_SCOPE */
+
+STATIC void
+S_clear_backtrack_stack(pTHX_ void *p)
+{
+    regmatch_slab *s = PL_regmatch_slab->next;
+    PERL_UNUSED_ARG(p);
+
+    if (!s)
+	return;
+    PL_regmatch_slab->next = NULL;
+    while (s) {
+	regmatch_slab * const osl = s;
+	s = s->next;
+	Safefree(osl);
+    }
+}
+
+
 #define SETREX(Re1,Re2) \
     if (PL_reg_eval_set) PM_SETRE((PL_reg_curpm), (Re2)); \
     Re1 = (Re2)
@@ -2609,8 +2629,7 @@ S_regmatch(pTHX_ regmatch_info *reginfo, regnode *prog)
     regexp *rex = reginfo->prog;
     RXi_GET_DECL(rex,rexi);
     
-    regmatch_slab  *orig_slab;
-    regmatch_state *orig_state;
+    I32	oldsave;
 
     /* the current state. This is a cached copy of PL_regmatch_state */
     register regmatch_state *st;
@@ -2682,10 +2701,10 @@ S_regmatch(pTHX_ regmatch_info *reginfo, regnode *prog)
 	PL_regmatch_state = SLAB_FIRST(PL_regmatch_slab);
     }
 
-    /* remember current high-water mark for exit */
-    /* XXX this should be done with SAVE* instead */
-    orig_slab  = PL_regmatch_slab;
-    orig_state = PL_regmatch_state;
+    oldsave = PL_savestack_ix;
+    SAVEDESTRUCTOR_X(S_clear_backtrack_stack, NULL);
+    SAVEVPTR(PL_regmatch_slab);
+    SAVEVPTR(PL_regmatch_state);
 
     /* grab next free state slot */
     st = ++PL_regmatch_state;
@@ -5133,20 +5152,8 @@ no_silent:
         sv_setsv(sv_mrk, sv_yes_mark);
     }
 
-    /* restore original high-water mark */
-    PL_regmatch_slab  = orig_slab;
-    PL_regmatch_state = orig_state;
-
-    /* free all slabs above current one */
-    if (orig_slab->next) {
-	regmatch_slab *sl = orig_slab->next;
-	orig_slab->next = NULL;
-	while (sl) {
-	    regmatch_slab * const osl = sl;
-	    sl = sl->next;
-	    Safefree(osl);
-	}
-    }
+    /* clean up; in particular, free all slabs above current one */
+    LEAVE_SCOPE(oldsave);
 
     return result;
 }