diff src/regexp_nfa.c @ 6328:adfbffe1e642 v7.4.497

updated for version 7.4.497 Problem: With some regexp patterns the NFA engine uses many states and becomes very slow. To the user it looks like Vim freezes. Solution: When the number of states reaches a limit fall back to the old engine. (Christian Brabandt)
author Bram Moolenaar <bram@vim.org>
date Wed, 05 Nov 2014 14:27:36 +0100
parents 7f2472960aa1
children 2bb019eb60ca
line wrap: on
line diff
--- a/src/regexp_nfa.c
+++ b/src/regexp_nfa.c
@@ -5522,6 +5522,13 @@ nfa_regmatch(prog, start, submatch, m)
 	nextlist->n = 0;	    /* clear nextlist */
 	nextlist->has_pim = FALSE;
 	++nfa_listid;
+	if (prog->re_engine == AUTOMATIC_ENGINE && nfa_listid >= NFA_MAX_STATES)
+	{
+	    /* too many states, retry with old engine */
+	    nfa_match = NFA_TOO_EXPENSIVE;
+	    goto theend;
+	}
+
 	thislist->id = nfa_listid;
 	nextlist->id = nfa_listid + 1;
 
@@ -5704,6 +5711,11 @@ nfa_regmatch(prog, start, submatch, m)
 			 */
 			result = recursive_regmatch(t->state, NULL, prog,
 						       submatch, m, &listids);
+			if (result == NFA_TOO_EXPENSIVE)
+			{
+			    nfa_match = result;
+			    goto theend;
+			}
 
 			/* for \@! and \@<! it is a match when the result is
 			 * FALSE */
@@ -5817,6 +5829,11 @@ nfa_regmatch(prog, start, submatch, m)
 		/* First try matching the pattern. */
 		result = recursive_regmatch(t->state, NULL, prog,
 						       submatch, m, &listids);
+		if (result == NFA_TOO_EXPENSIVE)
+		{
+		    nfa_match = result;
+		    goto theend;
+		}
 		if (result)
 		{
 		    int bytelen;
@@ -6760,6 +6777,7 @@ nfa_regtry(prog, col)
     int		i;
     regsubs_T	subs, m;
     nfa_state_T	*start = prog->start;
+    int		result;
 #ifdef ENABLE_LOG
     FILE	*f;
 #endif
@@ -6791,8 +6809,11 @@ nfa_regtry(prog, col)
     clear_sub(&m.synt);
 #endif
 
-    if (nfa_regmatch(prog, start, &subs, &m) == FALSE)
+    result = nfa_regmatch(prog, start, &subs, &m);
+    if (result == FALSE)
 	return 0;
+    else if (result == NFA_TOO_EXPENSIVE)
+	return result;
 
     cleanup_subexpr();
     if (REG_MULTI)
@@ -6929,9 +6950,7 @@ nfa_regexec_both(line, startcol)
     nfa_nsubexpr = prog->nsubexp;
     nfa_listid = 1;
     nfa_alt_listid = 2;
-#ifdef DEBUG
     nfa_regengine.expr = prog->pattern;
-#endif
 
     if (prog->reganch && col > 0)
 	return 0L;
@@ -6979,9 +6998,7 @@ nfa_regexec_both(line, startcol)
 
     retval = nfa_regtry(prog, col);
 
-#ifdef DEBUG
     nfa_regengine.expr = NULL;
-#endif
 
 theend:
     return retval;
@@ -7003,9 +7020,7 @@ nfa_regcomp(expr, re_flags)
     if (expr == NULL)
 	return NULL;
 
-#ifdef DEBUG
     nfa_regengine.expr = expr;
-#endif
 
     init_class_tab();
 
@@ -7082,10 +7097,8 @@ nfa_regcomp(expr, re_flags)
     /* Remember whether this pattern has any \z specials in it. */
     prog->reghasz = re_has_z;
 #endif
-#ifdef DEBUG
     prog->pattern = vim_strsave(expr);
     nfa_regengine.expr = NULL;
-#endif
 
 out:
     vim_free(post_start);
@@ -7099,9 +7112,7 @@ fail:
 #ifdef ENABLE_LOG
     nfa_postfix_dump(expr, FAIL);
 #endif
-#ifdef DEBUG
     nfa_regengine.expr = NULL;
-#endif
     goto out;
 }
 
@@ -7115,9 +7126,7 @@ nfa_regfree(prog)
     if (prog != NULL)
     {
 	vim_free(((nfa_regprog_T *)prog)->match_text);
-#ifdef DEBUG
 	vim_free(((nfa_regprog_T *)prog)->pattern);
-#endif
 	vim_free(prog);
     }
 }