]> granicus.if.org Git - vim/commitdiff
patch 8.2.3410: crash with linebreak, listchars and large tabstop v8.2.3410
authorBram Moolenaar <Bram@vim.org>
Tue, 7 Sep 2021 18:45:31 +0000 (20:45 +0200)
committerBram Moolenaar <Bram@vim.org>
Tue, 7 Sep 2021 18:45:31 +0000 (20:45 +0200)
Problem:    Crash with linebreak, listchars and large tabstop.
Solution:   Account for different size listchars for a tab. (closes #8841)

src/drawline.c
src/testdir/test_listlbr_utf8.vim
src/version.c

index 98d76930f36199704cde6656eabd760988bbe9cb..2ad83f4b5e089c3ef895de46f353736d3e624740 100644 (file)
@@ -2109,55 +2109,60 @@ win_line(
                        int     i;
                        int     saved_nextra = n_extra;
 
-#ifdef FEAT_CONCEAL
+# ifdef FEAT_CONCEAL
                        if (vcol_off > 0)
                            // there are characters to conceal
                            tab_len += vcol_off;
+
                        // boguscols before FIX_FOR_BOGUSCOLS macro from above
                        if (wp->w_p_list && wp->w_lcs_chars.tab1
                                                        && old_boguscols > 0
                                                        && n_extra > tab_len)
                            tab_len += n_extra - tab_len;
-#endif
-
-                       // if n_extra > 0, it gives the number of chars, to
+# endif
+                       // If n_extra > 0, it gives the number of chars, to
                        // use for a tab, else we need to calculate the width
-                       // for a tab
+                       // for a tab.
                        len = (tab_len * mb_char2len(wp->w_lcs_chars.tab2));
+                       if (wp->w_lcs_chars.tab3)
+                           len += mb_char2len(wp->w_lcs_chars.tab3);
                        if (n_extra > 0)
                            len += n_extra - tab_len;
                        c = wp->w_lcs_chars.tab1;
                        p = alloc(len + 1);
-                       vim_memset(p, ' ', len);
-                       p[len] = NUL;
-                       vim_free(p_extra_free);
-                       p_extra_free = p;
-                       for (i = 0; i < tab_len; i++)
+                       if (p == NULL)
+                           n_extra = 0;
+                       else
                        {
-                           int lcs = wp->w_lcs_chars.tab2;
-
-                           if (*p == NUL)
+                           vim_memset(p, ' ', len);
+                           p[len] = NUL;
+                           vim_free(p_extra_free);
+                           p_extra_free = p;
+                           for (i = 0; i < tab_len; i++)
                            {
-                               tab_len = i;
-                               break;
-                           }
-
-                           // if tab3 is given, need to change the char
-                           // for tab
-                           if (wp->w_lcs_chars.tab3 && i == tab_len - 1)
-                               lcs = wp->w_lcs_chars.tab3;
-                           mb_char2bytes(lcs, p);
-                           p += mb_char2len(lcs);
-                           n_extra += mb_char2len(lcs)
+                               int lcs = wp->w_lcs_chars.tab2;
+
+                               if (*p == NUL)
+                               {
+                                   tab_len = i;
+                                   break;
+                               }
+
+                               // if tab3 is given, use it for the last char
+                               if (wp->w_lcs_chars.tab3 && i == tab_len - 1)
+                                   lcs = wp->w_lcs_chars.tab3;
+                               p += mb_char2bytes(lcs, p);
+                               n_extra += mb_char2len(lcs)
                                                  - (saved_nextra > 0 ? 1 : 0);
+                           }
+                           p_extra = p_extra_free;
+# ifdef FEAT_CONCEAL
+                           // n_extra will be increased by FIX_FOX_BOGUSCOLS
+                           // macro below, so need to adjust for that here
+                           if (vcol_off > 0)
+                               n_extra -= vcol_off;
+# endif
                        }
-                       p_extra = p_extra_free;
-#ifdef FEAT_CONCEAL
-                       // n_extra will be increased by FIX_FOX_BOGUSCOLS
-                       // macro below, so need to adjust for that here
-                       if (vcol_off > 0)
-                           n_extra -= vcol_off;
-#endif
                    }
 #endif
 #ifdef FEAT_CONCEAL
index 6f12b5f5366778b96f59910db819d57b931408e5..0d77dbfd33d2d5ef0396a7670f6f4a8b26152684 100644 (file)
@@ -70,6 +70,16 @@ func Test_nolinebreak_with_list()
   call s:close_windows()
 endfunc
 
+" this was causing a crash
+func Test_linebreak_with_list_and_tabs()
+  set linebreak list listchars=tab:⇤\ ⇥ tabstop=100
+  new
+  call setline(1, "\t\t\ttext")
+  redraw
+  bwipe!
+  set nolinebreak nolist listchars&vim tabstop=8
+endfunc
+
 func Test_linebreak_with_nolist()
   call s:test_windows('setl nolist')
   call setline(1, "\t*mask = nil;")
index 0eb6899ed69a76d7fefc8a3da4aa2e357bcc3293..979c039baf85f1979320e5fd01b087589d8627f0 100644 (file)
@@ -755,6 +755,8 @@ static char *(features[]) =
 
 static int included_patches[] =
 {   /* Add new patch number below this line */
+/**/
+    3410,
 /**/
     3409,
 /**/