changeset 6533:bdc8e71633e4 v7.4.593

updated for version 7.4.593 Problem: Crash when searching for "x\{0,90000}". (Dominique Pelle) Solution: Bail out from the NFA engine when the max limit is much higher than the min limit.
author Bram Moolenaar <bram@vim.org>
date Tue, 27 Jan 2015 12:59:55 +0100
parents 357f273b9cbd
children 47b3f1674787
files src/regexp.c src/regexp_nfa.c src/version.c src/vim.h
diffstat 4 files changed, 21 insertions(+), 9 deletions(-) [+]
line wrap: on
line diff
--- a/src/regexp.c
+++ b/src/regexp.c
@@ -8081,7 +8081,8 @@ vim_regcomp(expr_arg, re_flags)
      * First try the NFA engine, unless backtracking was requested.
      */
     if (regexp_engine != BACKTRACKING_ENGINE)
-        prog = nfa_regengine.regcomp(expr, re_flags);
+        prog = nfa_regengine.regcomp(expr,
+		re_flags + (regexp_engine == AUTOMATIC_ENGINE ? RE_AUTO : 0));
     else
 	prog = bt_regengine.regcomp(expr, re_flags);
 
@@ -8105,16 +8106,14 @@ vim_regcomp(expr_arg, re_flags)
 #endif
 	/*
 	 * If the NFA engine failed, try the backtracking engine.
-	 * Disabled for now, both engines fail on the same patterns.
-	 * Re-enable when regcomp() fails when the pattern would work better
-	 * with the other engine.
-	 *
+	 * The NFA engine also fails for patterns that it can't handle well
+	 * but are still valid patterns, thus a retry should work.
+	 */
 	if (regexp_engine == AUTOMATIC_ENGINE)
 	{
+	    regexp_engine = BACKTRACKING_ENGINE;
 	    prog = bt_regengine.regcomp(expr, re_flags);
-	    regexp_engine == BACKTRACKING_ENGINE;
 	}
-	 */
     }
 
     if (prog != NULL)
--- a/src/regexp_nfa.c
+++ b/src/regexp_nfa.c
@@ -244,6 +244,9 @@ static char_u e_nul_found[] = N_("E865: 
 static char_u e_misplaced[] = N_("E866: (NFA regexp) Misplaced %c");
 static char_u e_ill_char_class[] = N_("E877: (NFA regexp) Invalid character class: %ld");
 
+/* re_flags passed to nfa_regcomp() */
+static int nfa_re_flags;
+
 /* NFA regexp \ze operator encountered. */
 static int nfa_has_zend;
 
@@ -2011,10 +2014,10 @@ nfa_regpiece()
 	     *  <atom>*  */
 	    if (minval == 0 && maxval == MAX_LIMIT)
 	    {
-		if (greedy)
+		if (greedy)		/* { { (match the braces) */
 		    /* \{}, \{0,} */
 		    EMIT(NFA_STAR);
-		else
+		else			/* { { (match the braces) */
 		    /* \{-}, \{-0,} */
 		    EMIT(NFA_STAR_NONGREEDY);
 		break;
@@ -2030,6 +2033,12 @@ nfa_regpiece()
 		return OK;
 	    }
 
+	    /* The engine is very inefficient (uses too many states) when the
+	     * maximum is much larger than the minimum.  Bail out if we can
+	     * use the other engine. */
+	    if ((nfa_re_flags & RE_AUTO) && maxval > minval + 200)
+		return FAIL;
+
 	    /* Ignore previous call to nfa_regatom() */
 	    post_ptr = post_start + my_post_start;
 	    /* Save parse state after the repeated atom and the \{} */
@@ -7046,6 +7055,7 @@ nfa_regcomp(expr, re_flags)
 	return NULL;
 
     nfa_regengine.expr = expr;
+    nfa_re_flags = re_flags;
 
     init_class_tab();
 
--- a/src/version.c
+++ b/src/version.c
@@ -742,6 +742,8 @@ static char *(features[]) =
 static int included_patches[] =
 {   /* Add new patch number below this line */
 /**/
+    593,
+/**/
     592,
 /**/
     591,
--- a/src/vim.h
+++ b/src/vim.h
@@ -1020,6 +1020,7 @@ extern char *(*dyn_libintl_textdomain)(c
 #define RE_MAGIC	1	/* 'magic' option */
 #define RE_STRING	2	/* match in string instead of buffer text */
 #define RE_STRICT	4	/* don't allow [abc] without ] */
+#define RE_AUTO		8	/* automatic engine selection */
 
 #ifdef FEAT_SYN_HL
 /* values for reg_do_extmatch */