To: vim_dev@googlegroups.com Subject: Patch 8.1.0170 Fcc: outbox From: Bram Moolenaar Mime-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit ------------ Patch 8.1.0170 Problem: Invalid memory use with complicated pattern. (Andy Massimino) Solution: Reallocate the list of listids when needed. (closes #3175) Remove unnecessary function prototypes. Files: src/regexp_nfa.c *** ../vim-8.1.0169/src/regexp_nfa.c Sat Jun 23 17:14:36 2018 --- src/regexp_nfa.c Sun Jul 8 19:03:46 2018 *************** *** 282,322 **** /* 0 for first call to nfa_regmatch(), 1 for recursive call. */ static int nfa_ll_index = 0; - static int nfa_regcomp_start(char_u *expr, int re_flags); - static int nfa_get_reganch(nfa_state_T *start, int depth); - static int nfa_get_regstart(nfa_state_T *start, int depth); - static char_u *nfa_get_match_text(nfa_state_T *start); static int realloc_post_list(void); - static int nfa_recognize_char_class(char_u *start, char_u *end, int extra_newl); - static int nfa_emit_equi_class(int c); - static int nfa_regatom(void); - static int nfa_regpiece(void); - static int nfa_regconcat(void); - static int nfa_regbranch(void); static int nfa_reg(int paren); #ifdef DEBUG - static void nfa_set_code(int c); - static void nfa_postfix_dump(char_u *expr, int retval); - static void nfa_print_state(FILE *debugf, nfa_state_T *state); static void nfa_print_state2(FILE *debugf, nfa_state_T *state, garray_T *indent); - static void nfa_dump(nfa_regprog_T *prog); #endif - static int *re2post(void); - static nfa_state_T *alloc_state(int c, nfa_state_T *out, nfa_state_T *out1); - static void st_error(int *postfix, int *end, int *p); - static int nfa_max_width(nfa_state_T *startstate, int depth); - static nfa_state_T *post2nfa(int *postfix, int *end, int nfa_calc_size); - static void nfa_postprocess(nfa_regprog_T *prog); - static int check_char_class(int class, int c); - static void nfa_save_listids(nfa_regprog_T *prog, int *list); - static void nfa_restore_listids(nfa_regprog_T *prog, int *list); - static int nfa_re_num_cmp(long_u val, int op, long_u pos); - static long nfa_regtry(nfa_regprog_T *prog, colnr_T col, proftime_T *tm, int *timed_out); - static long nfa_regexec_both(char_u *line, colnr_T col, proftime_T *tm, int *timed_out); - static regprog_T *nfa_regcomp(char_u *expr, int re_flags); - static void nfa_regfree(regprog_T *prog); - static int nfa_regexec_nl(regmatch_T *rmp, char_u *line, colnr_T col, int line_lbr); - static long nfa_regexec_multi(regmmatch_T *rmp, win_T *win, buf_T *buf, linenr_T lnum, colnr_T col, proftime_T *tm, int *timed_out); static int match_follows(nfa_state_T *startstate, int depth); static int failure_chance(nfa_state_T *state, int depth); --- 282,292 ---- *************** *** 2876,2888 **** }; typedef struct Frag Frag_T; - static Frag_T frag(nfa_state_T *start, Ptrlist *out); - static Ptrlist *list1(nfa_state_T **outp); - static void patch(Ptrlist *l, nfa_state_T *s); - static Ptrlist *append(Ptrlist *l1, Ptrlist *l2); - static void st_push(Frag_T s, Frag_T **p, Frag_T *stack_end); - static Frag_T st_pop(Frag_T **p, Frag_T *stack); - /* * Initialize a Frag_T struct and return it. */ --- 2846,2851 ---- *************** *** 3917,3925 **** } nfa_list_T; #ifdef ENABLE_LOG - static void log_subsexpr(regsubs_T *subs); static void log_subexpr(regsub_T *sub); - static char *pim_info(nfa_pim_T *pim); static void log_subsexpr(regsubs_T *subs) --- 3880,3886 ---- *************** *** 3974,3998 **** #endif /* Used during execution: whether a match has been found. */ ! static int nfa_match; #ifdef FEAT_RELTIME static proftime_T *nfa_time_limit; static int *nfa_timed_out; static int nfa_time_count; #endif - static void copy_pim(nfa_pim_T *to, nfa_pim_T *from); - static void clear_sub(regsub_T *sub); static void copy_sub(regsub_T *to, regsub_T *from); - static void copy_sub_off(regsub_T *to, regsub_T *from); - static void copy_ze_off(regsub_T *to, regsub_T *from); - static int sub_equal(regsub_T *sub1, regsub_T *sub2); - static int match_backref(regsub_T *sub, int subidx, int *bytelen); - static int has_state_with_pos(nfa_list_T *l, nfa_state_T *state, regsubs_T *subs, nfa_pim_T *pim); static int pim_equal(nfa_pim_T *one, nfa_pim_T *two); - static int state_in_list(nfa_list_T *l, nfa_state_T *state, regsubs_T *subs); - static regsubs_T *addstate(nfa_list_T *l, nfa_state_T *state, regsubs_T *subs_arg, nfa_pim_T *pim, int off); - static void addstate_here(nfa_list_T *l, nfa_state_T *state, regsubs_T *subs, nfa_pim_T *pim, int *ip); /* * Copy postponed invisible match info from "from" to "to". --- 3935,3949 ---- #endif /* Used during execution: whether a match has been found. */ ! static int nfa_match; #ifdef FEAT_RELTIME static proftime_T *nfa_time_limit; static int *nfa_timed_out; static int nfa_time_count; #endif static void copy_sub(regsub_T *to, regsub_T *from); static int pim_equal(nfa_pim_T *one, nfa_pim_T *two); /* * Copy postponed invisible match info from "from" to "to". *************** *** 5018,5025 **** #ifdef FEAT_SYN_HL - static int match_zref(int subidx, int *bytelen); - /* * Check for a match with \z subexpression "subidx". * Return TRUE if it matches. --- 4969,4974 ---- *************** *** 5095,5101 **** return val == pos; } - 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 nfa_regmatch(nfa_regprog_T *prog, nfa_state_T *start, regsubs_T *submatch, regsubs_T *m); /* --- 5044,5049 ---- *************** *** 5110,5116 **** nfa_regprog_T *prog, regsubs_T *submatch, regsubs_T *m, ! int **listids) { int save_reginput_col = (int)(reginput - regline); int save_reglnum = reglnum; --- 5058,5065 ---- 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; *************** *** 5212,5225 **** { /* Already calling nfa_regmatch() recursively. Save the lastlist[1] * values and clear them. */ ! if (*listids == NULL) { *listids = (int *)lalloc(sizeof(int) * nstate, TRUE); if (*listids == NULL) { EMSG(_("E878: (NFA) Could not allocate memory for branch traversal!")); return 0; } } nfa_save_listids(prog, *listids); need_restore = TRUE; --- 5161,5176 ---- { /* Already calling nfa_regmatch() recursively. Save the lastlist[1] * values and clear them. */ ! if (*listids == NULL || *listids_len < nstate) { + vim_free(*listids); *listids = (int *)lalloc(sizeof(int) * nstate, TRUE); if (*listids == NULL) { EMSG(_("E878: (NFA) Could not allocate memory for branch traversal!")); return 0; } + *listids_len = nstate; } nfa_save_listids(prog, *listids); need_restore = TRUE; *************** *** 5279,5287 **** return result; } - static int skip_to_start(int c, colnr_T *colp); - static long find_match_text(colnr_T startcol, int regstart, char_u *match_text); - /* * Estimate the chance of a match with "state" failing. * empty match: 0 --- 5230,5235 ---- *************** *** 5570,5575 **** --- 5518,5524 ---- nfa_list_T *thislist; nfa_list_T *nextlist; int *listids = NULL; + int listids_len = 0; nfa_state_T *add_state; int add_here; int add_count; *************** *** 5898,5904 **** * follows. */ result = recursive_regmatch(t->state, NULL, prog, ! submatch, m, &listids); if (result == NFA_TOO_EXPENSIVE) { nfa_match = result; --- 5847,5853 ---- * follows. */ result = recursive_regmatch(t->state, NULL, prog, ! submatch, m, &listids, &listids_len); if (result == NFA_TOO_EXPENSIVE) { nfa_match = result; *************** *** 6016,6022 **** /* First try matching the pattern. */ result = recursive_regmatch(t->state, NULL, prog, ! submatch, m, &listids); if (result == NFA_TOO_EXPENSIVE) { nfa_match = result; --- 5965,5971 ---- /* First try matching the pattern. */ result = recursive_regmatch(t->state, NULL, prog, ! submatch, m, &listids, &listids_len); if (result == NFA_TOO_EXPENSIVE) { nfa_match = result; *************** *** 6783,6789 **** fprintf(log_fd, "\n"); #endif result = recursive_regmatch(pim->state, pim, ! prog, submatch, m, &listids); pim->result = result ? NFA_PIM_MATCH : NFA_PIM_NOMATCH; /* for \@! and \@state, pim, ! prog, submatch, m, &listids, &listids_len); pim->result = result ? NFA_PIM_MATCH : NFA_PIM_NOMATCH; /* for \@! and \@