diff options
Diffstat (limited to 'src/nvim/regexp_nfa.c')
-rw-r--r-- | src/nvim/regexp_nfa.c | 80 |
1 files changed, 62 insertions, 18 deletions
diff --git a/src/nvim/regexp_nfa.c b/src/nvim/regexp_nfa.c index 95030974d8..b935b44291 100644 --- a/src/nvim/regexp_nfa.c +++ b/src/nvim/regexp_nfa.c @@ -1338,8 +1338,15 @@ static int nfa_regatom(void) case Magic('7'): case Magic('8'): case Magic('9'): - EMIT(NFA_BACKREF1 + (no_Magic(c) - '1')); - nfa_has_backref = TRUE; + { + int refnum = no_Magic(c) - '1'; + + if (!seen_endbrace(refnum + 1)) { + return FAIL; + } + EMIT(NFA_BACKREF1 + refnum); + nfa_has_backref = true; + } break; case Magic('z'): @@ -3568,6 +3575,7 @@ static char *pim_info(nfa_pim_T *pim) // Used during execution: whether a match has been found. static int nfa_match; static proftime_T *nfa_time_limit; +static int *nfa_timed_out; static int nfa_time_count; // Copy postponed invisible match info from "from" to "to". @@ -4574,7 +4582,9 @@ static bool nfa_re_num_cmp(uintmax_t val, int op, uintmax_t pos) * "pim" is NULL or contains info about a Postponed Invisible Match (start * position). */ -static int recursive_regmatch(nfa_state_T *state, nfa_pim_T *pim, nfa_regprog_T *prog, regsubs_T *submatch, regsubs_T *m, int **listids) +static int recursive_regmatch( + nfa_state_T *state, nfa_pim_T *pim, nfa_regprog_T *prog, + regsubs_T *submatch, regsubs_T *m, int **listids, int *listids_len) { int save_reginput_col = (int)(reginput - regline); int save_reglnum = reglnum; @@ -4657,8 +4667,10 @@ static int recursive_regmatch(nfa_state_T *state, nfa_pim_T *pim, nfa_regprog_T if (nfa_ll_index == 1) { /* Already calling nfa_regmatch() recursively. Save the lastlist[1] * values and clear them. */ - if (*listids == NULL) { + if (*listids == NULL || *listids_len < nstate) { + xfree(*listids); *listids = xmalloc(sizeof(**listids) * nstate); + *listids_len = nstate; } nfa_save_listids(prog, *listids); need_restore = TRUE; @@ -4939,6 +4951,17 @@ static long find_match_text(colnr_T startcol, int regstart, char_u *match_text) #undef PTR2LEN } +static int nfa_did_time_out(void) +{ + if (nfa_time_limit != NULL && profile_passed_limit(*nfa_time_limit)) { + if (nfa_timed_out != NULL) { + *nfa_timed_out = true; + } + return true; + } + return false; +} + /// Main matching routine. /// /// Run NFA to determine whether it matches reginput. @@ -4960,6 +4983,7 @@ static int nfa_regmatch(nfa_regprog_T *prog, nfa_state_T *start, nfa_list_T *thislist; nfa_list_T *nextlist; int *listids = NULL; + int listids_len = 0; nfa_state_T *add_state; bool add_here; int add_count; @@ -4982,7 +5006,7 @@ static int nfa_regmatch(nfa_regprog_T *prog, nfa_state_T *start, #endif return false; } - if (nfa_time_limit != NULL && profile_passed_limit(*nfa_time_limit)) { + if (nfa_did_time_out()) { #ifdef NFA_REGEXP_DEBUG_LOG fclose(debug); #endif @@ -5095,8 +5119,20 @@ static int nfa_regmatch(nfa_regprog_T *prog, nfa_state_T *start, if (thislist->n == 0) break; - /* compute nextlist */ - for (listidx = 0; listidx < thislist->n; ++listidx) { + // compute nextlist + for (listidx = 0; listidx < thislist->n; listidx++) { + // If the list gets very long there probably is something wrong. + // At least allow interrupting with CTRL-C. + fast_breakcheck(); + if (got_int) { + break; + } + if (nfa_time_limit != NULL && ++nfa_time_count == 20) { + nfa_time_count = 0; + if (nfa_did_time_out()) { + break; + } + } t = &thislist->t[listidx]; #ifdef NFA_REGEXP_DEBUG_LOG @@ -5240,7 +5276,7 @@ static int nfa_regmatch(nfa_regprog_T *prog, nfa_state_T *start, // First try matching the invisible match, then what // follows. result = recursive_regmatch(t->state, NULL, prog, submatch, m, - &listids); + &listids, &listids_len); if (result == NFA_TOO_EXPENSIVE) { nfa_match = result; goto theend; @@ -5341,7 +5377,7 @@ static int nfa_regmatch(nfa_regprog_T *prog, nfa_state_T *start, // First try matching the pattern. result = recursive_regmatch(t->state, NULL, prog, submatch, m, - &listids); + &listids, &listids_len); if (result == NFA_TOO_EXPENSIVE) { nfa_match = result; goto theend; @@ -6048,8 +6084,8 @@ static int nfa_regmatch(nfa_regprog_T *prog, nfa_state_T *start, fprintf(log_fd, "Postponed recursive nfa_regmatch()\n"); fprintf(log_fd, "\n"); #endif - result = recursive_regmatch(pim->state, pim, - prog, submatch, m, &listids); + result = recursive_regmatch(pim->state, pim, prog, submatch, m, + &listids, &listids_len); pim->result = result ? NFA_PIM_MATCH : NFA_PIM_NOMATCH; // for \@! and \@<! it is a match when the result is // FALSE @@ -6218,7 +6254,7 @@ nextchar: // Check for timeout once every twenty times to avoid overhead. if (nfa_time_limit != NULL && ++nfa_time_count == 20) { nfa_time_count = 0; - if (profile_passed_limit(*nfa_time_limit)) { + if (nfa_did_time_out()) { break; } } @@ -6245,7 +6281,10 @@ theend: // Try match of "prog" with at regline["col"]. // Returns <= 0 for failure, number of lines contained in the match otherwise. -static long nfa_regtry(nfa_regprog_T *prog, colnr_T col, proftime_T *tm) +static long nfa_regtry(nfa_regprog_T *prog, + colnr_T col, + proftime_T *tm, // timeout limit or NULL + int *timed_out) // flag set on timeout or NULL { int i; regsubs_T subs, m; @@ -6256,6 +6295,7 @@ static long nfa_regtry(nfa_regprog_T *prog, colnr_T col, proftime_T *tm) reginput = regline + col; nfa_time_limit = tm; + nfa_timed_out = timed_out; nfa_time_count = 0; #ifdef REGEXP_DEBUG @@ -6364,10 +6404,12 @@ static long nfa_regtry(nfa_regprog_T *prog, colnr_T col, proftime_T *tm) /// @param line String in which to search or NULL /// @param startcol Column to start looking for match /// @param tm Timeout limit or NULL +/// @param timed_out Flag set on timeout or NULL /// /// @return <= 0 if there is no match and number of lines contained in the /// match otherwise. -static long nfa_regexec_both(char_u *line, colnr_T startcol, proftime_T *tm) +static long nfa_regexec_both(char_u *line, colnr_T startcol, + proftime_T *tm, int *timed_out) { nfa_regprog_T *prog; long retval = 0L; @@ -6449,7 +6491,7 @@ static long nfa_regexec_both(char_u *line, colnr_T startcol, proftime_T *tm) prog->state[i].lastlist[1] = 0; } - retval = nfa_regtry(prog, col, tm); + retval = nfa_regtry(prog, col, tm, timed_out); nfa_regengine.expr = NULL; @@ -6596,7 +6638,7 @@ nfa_regexec_nl ( rex.reg_ic = rmp->rm_ic; rex.reg_icombine = false; rex.reg_maxcol = 0; - return nfa_regexec_both(line, col, NULL); + return nfa_regexec_both(line, col, NULL, NULL); } /// Matches a regexp against multiple lines. @@ -6608,6 +6650,7 @@ nfa_regexec_nl ( /// @param lnum Number of line to start looking for match /// @param col Column to start looking for match /// @param tm Timeout limit or NULL +/// @param timed_out Flag set on timeout or NULL /// /// @return <= 0 if there is no match and number of lines contained in the match /// otherwise. @@ -6634,7 +6677,8 @@ nfa_regexec_nl ( /// @par /// FIXME if this behavior is not compatible. static long nfa_regexec_multi(regmmatch_T *rmp, win_T *win, buf_T *buf, - linenr_T lnum, colnr_T col, proftime_T *tm) + linenr_T lnum, colnr_T col, + proftime_T *tm, int *timed_out) { rex.reg_match = NULL; rex.reg_mmatch = rmp; @@ -6647,5 +6691,5 @@ static long nfa_regexec_multi(regmmatch_T *rmp, win_T *win, buf_T *buf, rex.reg_icombine = false; rex.reg_maxcol = rmp->rmm_maxcol; - return nfa_regexec_both(NULL, col, tm); + return nfa_regexec_both(NULL, col, tm, timed_out); } |