Skip to content

Commit 89a54b4

Browse files
committed
patch 8.2.3410: crash with linebreak, listchars and large tabstop
Problem: Crash with linebreak, listchars and large tabstop. Solution: Account for different size listchars for a tab. (closes #8841)
1 parent 65b6056 commit 89a54b4

3 files changed

Lines changed: 48 additions & 31 deletions

File tree

src/drawline.c

Lines changed: 36 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -2109,55 +2109,60 @@ win_line(
21092109
int i;
21102110
int saved_nextra = n_extra;
21112111

2112-
#ifdef FEAT_CONCEAL
2112+
# ifdef FEAT_CONCEAL
21132113
if (vcol_off > 0)
21142114
// there are characters to conceal
21152115
tab_len += vcol_off;
2116+
21162117
// boguscols before FIX_FOR_BOGUSCOLS macro from above
21172118
if (wp->w_p_list && wp->w_lcs_chars.tab1
21182119
&& old_boguscols > 0
21192120
&& n_extra > tab_len)
21202121
tab_len += n_extra - tab_len;
2121-
#endif
2122-
2123-
// if n_extra > 0, it gives the number of chars, to
2122+
# endif
2123+
// If n_extra > 0, it gives the number of chars, to
21242124
// use for a tab, else we need to calculate the width
2125-
// for a tab
2125+
// for a tab.
21262126
len = (tab_len * mb_char2len(wp->w_lcs_chars.tab2));
2127+
if (wp->w_lcs_chars.tab3)
2128+
len += mb_char2len(wp->w_lcs_chars.tab3);
21272129
if (n_extra > 0)
21282130
len += n_extra - tab_len;
21292131
c = wp->w_lcs_chars.tab1;
21302132
p = alloc(len + 1);
2131-
vim_memset(p, ' ', len);
2132-
p[len] = NUL;
2133-
vim_free(p_extra_free);
2134-
p_extra_free = p;
2135-
for (i = 0; i < tab_len; i++)
2133+
if (p == NULL)
2134+
n_extra = 0;
2135+
else
21362136
{
2137-
int lcs = wp->w_lcs_chars.tab2;
2138-
2139-
if (*p == NUL)
2137+
vim_memset(p, ' ', len);
2138+
p[len] = NUL;
2139+
vim_free(p_extra_free);
2140+
p_extra_free = p;
2141+
for (i = 0; i < tab_len; i++)
21402142
{
2141-
tab_len = i;
2142-
break;
2143-
}
2144-
2145-
// if tab3 is given, need to change the char
2146-
// for tab
2147-
if (wp->w_lcs_chars.tab3 && i == tab_len - 1)
2148-
lcs = wp->w_lcs_chars.tab3;
2149-
mb_char2bytes(lcs, p);
2150-
p += mb_char2len(lcs);
2151-
n_extra += mb_char2len(lcs)
2143+
int lcs = wp->w_lcs_chars.tab2;
2144+
2145+
if (*p == NUL)
2146+
{
2147+
tab_len = i;
2148+
break;
2149+
}
2150+
2151+
// if tab3 is given, use it for the last char
2152+
if (wp->w_lcs_chars.tab3 && i == tab_len - 1)
2153+
lcs = wp->w_lcs_chars.tab3;
2154+
p += mb_char2bytes(lcs, p);
2155+
n_extra += mb_char2len(lcs)
21522156
- (saved_nextra > 0 ? 1 : 0);
2157+
}
2158+
p_extra = p_extra_free;
2159+
# ifdef FEAT_CONCEAL
2160+
// n_extra will be increased by FIX_FOX_BOGUSCOLS
2161+
// macro below, so need to adjust for that here
2162+
if (vcol_off > 0)
2163+
n_extra -= vcol_off;
2164+
# endif
21532165
}
2154-
p_extra = p_extra_free;
2155-
#ifdef FEAT_CONCEAL
2156-
// n_extra will be increased by FIX_FOX_BOGUSCOLS
2157-
// macro below, so need to adjust for that here
2158-
if (vcol_off > 0)
2159-
n_extra -= vcol_off;
2160-
#endif
21612166
}
21622167
#endif
21632168
#ifdef FEAT_CONCEAL

src/testdir/test_listlbr_utf8.vim

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -70,6 +70,16 @@ func Test_nolinebreak_with_list()
7070
call s:close_windows()
7171
endfunc
7272

73+
" this was causing a crash
74+
func Test_linebreak_with_list_and_tabs()
75+
set linebreak list listchars=tab:⇤\ tabstop=100
76+
new
77+
call setline(1, "\t\t\ttext")
78+
redraw
79+
bwipe!
80+
set nolinebreak nolist listchars&vim tabstop=8
81+
endfunc
82+
7383
func Test_linebreak_with_nolist()
7484
call s:test_windows('setl nolist')
7585
call setline(1, "\t*mask = nil;")

src/version.c

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -755,6 +755,8 @@ static char *(features[]) =
755755

756756
static int included_patches[] =
757757
{ /* Add new patch number below this line */
758+
/**/
759+
3410,
758760
/**/
759761
3409,
760762
/**/

0 commit comments

Comments
 (0)