changeset 27000:8c0730eca2ce v8.2.4029

patch 8.2.4029: debugging NFA regexp my crash, cached indent may be wrong Commit: https://github.com/vim/vim/commit/b2d85e3784ac89f5209489844c1ee0f54d117abb Author: Bram Moolenaar <Bram@vim.org> Date: Fri Jan 7 16:55:32 2022 +0000 patch 8.2.4029: debugging NFA regexp my crash, cached indent may be wrong Problem: Debugging NFA regexp my crash, cached indent may be wrong. Solution: Fix some debug warnings in the NFA regexp code. Make sure log_fd is set when used. Fix breakindent and indent caching. (Christian Brabandt, closes #9482)
author Bram Moolenaar <Bram@vim.org>
date Fri, 07 Jan 2022 18:00:04 +0100
parents aba0728a28d9
children d3404d1f5478
files src/indent.c src/optionstr.c src/regexp_nfa.c src/version.c
diffstat 4 files changed, 76 insertions(+), 45 deletions(-) [+]
line wrap: on
line diff
--- a/src/indent.c
+++ b/src/indent.c
@@ -915,13 +915,15 @@ get_breakindent_win(
     win_T	*wp,
     char_u	*line) // start of the line
 {
-    static int	    prev_indent = 0;  // cached indent value
-    static long	    prev_ts     = 0L; // cached tabstop value
-    static char_u   *prev_line = NULL; // cached pointer to line
+    static int	    prev_indent = 0;	// cached indent value
+    static long	    prev_ts     = 0L;	// cached tabstop value
+    static char_u   *prev_line = NULL;	// cached pointer to line
     static varnumber_T prev_tick = 0;   // changedtick of cached value
 # ifdef FEAT_VARTABS
-    static int      *prev_vts = NULL;    // cached vartabs values
+    static int      *prev_vts = NULL;   // cached vartabs values
 # endif
+    static int      prev_list = 0;	// cached list value
+    static int      prev_listopt = 0;	// cached w_p_briopt_list value
     int		    bri = 0;
     // window width minus window margin space, i.e. what rests for text
     const int	    eff_wwidth = wp->w_width
@@ -929,9 +931,10 @@ get_breakindent_win(
 				&& (vim_strchr(p_cpo, CPO_NUMCOL) == NULL)
 						? number_width(wp) + 1 : 0);
 
-    // used cached indent, unless pointer or 'tabstop' changed
+    // used cached indent, unless line, 'tabstop' or briopt_list changed
     if (prev_line != line || prev_ts != wp->w_buffer->b_p_ts
 	    || prev_tick != CHANGEDTICK(wp->w_buffer)
+	    || prev_listopt != wp->w_briopt_list
 # ifdef FEAT_VARTABS
 	    || prev_vts != wp->w_buffer->b_p_vts_array
 # endif
@@ -949,6 +952,28 @@ get_breakindent_win(
 	prev_indent = get_indent_str(line,
 				     (int)wp->w_buffer->b_p_ts, wp->w_p_list);
 # endif
+	prev_listopt = wp->w_briopt_list;
+	// add additional indent for numbered lists
+	if (wp->w_briopt_list != 0)
+	{
+	    regmatch_T	    regmatch;
+
+	    regmatch.regprog = vim_regcomp(curbuf->b_p_flp,
+				       RE_MAGIC + RE_STRING + RE_AUTO + RE_STRICT);
+
+	    if (regmatch.regprog != NULL)
+	    {
+		regmatch.rm_ic = FALSE;
+		if (vim_regexec(&regmatch, line, 0))
+		{
+		    if (wp->w_briopt_list > 0)
+			prev_list = wp->w_briopt_list;
+		    else
+			prev_list = (*regmatch.endp - *regmatch.startp);
+		}
+		vim_regfree(regmatch.regprog);
+	    }
+	}
     }
     bri = prev_indent + wp->w_briopt_shift;
 
@@ -958,22 +983,10 @@ get_breakindent_win(
     // add additional indent for numbered lists
     if (wp->w_briopt_list != 0)
     {
-	regmatch_T	    regmatch;
-
-	regmatch.regprog = vim_regcomp(curbuf->b_p_flp,
-				   RE_MAGIC + RE_STRING + RE_AUTO + RE_STRICT);
-	if (regmatch.regprog != NULL)
-	{
-	    regmatch.rm_ic = FALSE;
-	    if (vim_regexec(&regmatch, line, 0))
-	    {
-		if (wp->w_briopt_list > 0)
-		    bri += wp->w_briopt_list;
-		else
-		    bri = (*regmatch.endp - *regmatch.startp);
-	    }
-	    vim_regfree(regmatch.regprog);
-	}
+	if (wp->w_briopt_list > 0)
+	    bri += prev_list;
+	else
+	    bri = prev_list;
     }
 
     // indent minus the length of the showbreak string
--- a/src/optionstr.c
+++ b/src/optionstr.c
@@ -756,6 +756,9 @@ did_set_string_option(
     {
 	if (briopt_check(curwin) == FAIL)
 	    errmsg = e_invalid_argument;
+	// list setting requires a redraw
+	if (curwin->w_briopt_list)
+	    redraw_all_later(NOT_VALID);
     }
 #endif
 
@@ -2610,6 +2613,14 @@ ambw_end:
 	update_package_paths_in_lua();
 #endif
 
+#if defined(FEAT_LINEBREAK)
+    // Changing Formatlistpattern when briopt includes the list setting:
+    // redraw
+    if ((varp == &p_flp || varp == &(curbuf->b_p_flp))
+	    && curwin->w_briopt_list)
+	redraw_all_later(NOT_VALID);
+#endif
+
     if (curwin->w_curswant != MAXCOL
 		   && (get_option_flags(opt_idx) & (P_CURSWANT | P_RALL)) != 0)
 	curwin->w_set_curswant = TRUE;
--- a/src/regexp_nfa.c
+++ b/src/regexp_nfa.c
@@ -2885,7 +2885,7 @@ nfa_print_state2(FILE *debugf, nfa_state
 	char_u	save[2];
 
 	STRNCPY(save, &p[last], 2);
-	STRNCPY(&p[last], "+-", 2);
+	memcpy(&p[last], "+-", 2);
 	fprintf(debugf, " %s", p);
 	STRNCPY(&p[last], save, 2);
     }
@@ -4292,6 +4292,23 @@ sub_equal(regsub_T *sub1, regsub_T *sub2
 
 #ifdef ENABLE_LOG
     static void
+open_debug_log(int result)
+{
+    log_fd = fopen(NFA_REGEXP_RUN_LOG, "a");
+    if (log_fd == NULL)
+    {
+	emsg(_(e_log_open_failed));
+	log_fd = stderr;
+    }
+
+    fprintf(log_fd, "****************************\n");
+    fprintf(log_fd, "FINISHED RUNNING nfa_regmatch() recursively\n");
+    fprintf(log_fd, "MATCH = %s\n", result == TRUE ? "OK" : result == MAYBE
+	    ? "MAYBE" : "FALSE");
+    fprintf(log_fd, "****************************\n");
+}
+
+    static void
 report_state(char *action,
 	     regsub_T *sub,
 	     nfa_state_T *state,
@@ -4307,6 +4324,9 @@ report_state(char *action,
     else
 	col = (int)(sub->list.line[0].start - rex.line);
     nfa_set_code(state->c);
+    if (log_fd == NULL)
+	open_debug_log(MAYBE);
+
     fprintf(log_fd, "> %s state %d to list %d. char %d: %s (start col %d)%s\n",
 	    action, abs(state->id), lid, state->c, code, col,
 	    pim_info(pim));
@@ -5430,19 +5450,7 @@ recursive_regmatch(
     nfa_endp = save_nfa_endp;
 
 #ifdef ENABLE_LOG
-    log_fd = fopen(NFA_REGEXP_RUN_LOG, "a");
-    if (log_fd != NULL)
-    {
-	fprintf(log_fd, "****************************\n");
-	fprintf(log_fd, "FINISHED RUNNING nfa_regmatch() recursively\n");
-	fprintf(log_fd, "MATCH = %s\n", result == TRUE ? "OK" : "FALSE");
-	fprintf(log_fd, "****************************\n");
-    }
-    else
-    {
-	emsg(_(e_log_open_failed));
-	log_fd = stderr;
-    }
+    open_debug_log(result);
 #endif
 
     return result;
@@ -5775,19 +5783,16 @@ nfa_regmatch(
 
 #ifdef ENABLE_LOG
     log_fd = fopen(NFA_REGEXP_RUN_LOG, "a");
-    if (log_fd != NULL)
-    {
-	fprintf(log_fd, "**********************************\n");
-	nfa_set_code(start->c);
-	fprintf(log_fd, " RUNNING nfa_regmatch() starting with state %d, code %s\n",
-	abs(start->id), code);
-	fprintf(log_fd, "**********************************\n");
-    }
-    else
+    if (log_fd == NULL)
     {
 	emsg(_(e_log_open_failed));
 	log_fd = stderr;
     }
+    fprintf(log_fd, "**********************************\n");
+    nfa_set_code(start->c);
+    fprintf(log_fd, " RUNNING nfa_regmatch() starting with state %d, code %s\n",
+    abs(start->id), code);
+    fprintf(log_fd, "**********************************\n");
 #endif
 
     thislist = &list[0];
@@ -6919,7 +6924,7 @@ nfa_regmatch(
 
 #ifdef DEBUG
 		if (c < 0)
-		    siemsg("INTERNAL: Negative state char: %ld", c);
+		    siemsg("INTERNAL: Negative state char: %ld", (long)c);
 #endif
 		result = (c == curc);
 
--- a/src/version.c
+++ b/src/version.c
@@ -751,6 +751,8 @@ static char *(features[]) =
 static int included_patches[] =
 {   /* Add new patch number below this line */
 /**/
+    4029,
+/**/
     4028,
 /**/
     4027,