Mercurial > vim
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); } }