mirror of
https://github.com/neovim/neovim.git
synced 2026-06-15 08:13:45 +00:00
vim-patch:9.2.0642: statusline: buffer overflow with item groups (#40253)
Problem: statusline: buffer overflow with item groups
Solution: Fix the issues (see below) (Sébastien Hoffmann)
Fix various buffer overflow bugs (examples assume MAXPATHL==4096):
- truncated item groups where minwid>maxwid:
vim --clean +"set ls=2 stl=%<%{%repeat('x',4096-11)%}%50.5(12🙂345%)"
leads to fillchars spilling over the end of the group/buffer while trying to
compensate for truncating at a multicell character because minwid<=maxwid is assumed
- left-aligned item groups with multi-byte fillchar:
vim --clean +"set ls=2 fillchars+=stl:∙ stl=%<%{%repeat('x',4096-3)%}%-2(X%)"
wrongly leads to padding at the end of the statusline and `p-out==4097`
because the bounds check assumes a 1-byte fillchar
- right-aligned item groups with 1-byte fillchar:
vim --clean +"set ls=2 stl=%<%{%repeat('x',4096-4)%}%4(XY%)"
leads to "YX" instead of "XY" at the end of the statusline
because `memmove` is done before adjusting the offset
- right-aligned item groups with multi-byte fillchar:
vim --clean +"set ls=2 fillchars+=stl:∙ stl=%5(X%)"
leads to "∙∙∙∙<e2>", i.e. the fillchar is being written over the group contents
and eventually being overwritten itself at the second byte with the final NUL,
because the padding counter assumes a 1-byte fillchar; to crash vim,
vim --clean +"set ls=2 fillchars+=stl:∙ stl=%<%{%repeat('x',4096-149)%}%50(X%)"
related: neovim/neovim#40219
closes: vim/vim#20522
d249884340
Co-authored-by: Sébastien Hoffmann <contact@shoffmann.dev>
This commit is contained in:
@@ -1147,8 +1147,8 @@ int build_stl_str_hl(win_T *wp, char *out, size_t outlen, char *fmt, OptIndex op
|
||||
memmove(t + 1, t + n, (size_t)(out_p - (t + n)));
|
||||
out_p = out_p - n + 1;
|
||||
// Fill up space left over by half a double-wide char.
|
||||
minwid = MIN(minwid, maxwid);
|
||||
while (++group_len < minwid) {
|
||||
int minwid_fixed = MIN(minwid, maxwid);
|
||||
while (++group_len < minwid_fixed) {
|
||||
schar_get_adv(&out_p, fillchar);
|
||||
}
|
||||
// }
|
||||
@@ -1187,15 +1187,15 @@ int build_stl_str_hl(win_T *wp, char *out, size_t outlen, char *fmt, OptIndex op
|
||||
out_p += added_bytes;
|
||||
// }
|
||||
|
||||
// Adjust item start positions
|
||||
for (int n = stl_groupitems[groupdepth] + 1; n < curitem; n++) {
|
||||
stl_items[n].start += added_bytes;
|
||||
}
|
||||
|
||||
// Prepend the fill characters
|
||||
for (; added_cells > 0; added_cells--) {
|
||||
schar_get_adv(&t, fillchar);
|
||||
}
|
||||
|
||||
// Adjust item start positions
|
||||
for (int n = stl_groupitems[groupdepth] + 1; n < curitem; n++) {
|
||||
stl_items[n].start += added_bytes;
|
||||
}
|
||||
}
|
||||
}
|
||||
continue;
|
||||
|
||||
@@ -124,10 +124,30 @@ func Test_statusline()
|
||||
call assert_match('^ Xstatusline\s*$', s:get_statusline())
|
||||
set statusline=%.6(%f%)
|
||||
call assert_match('^<sline\s*$', s:get_statusline())
|
||||
set statusline=%.5(1234567%),%2.5(1234567%),%5.5(1234567%),%50.5(1234567%)
|
||||
call assert_match('^<4567,<4567,<4567,<4567\s*$', s:get_statusline())
|
||||
set statusline=%14f
|
||||
call assert_match('^ Xstatusline\s*$', s:get_statusline())
|
||||
set statusline=%.4L
|
||||
call assert_match('^10>3\s*$', s:get_statusline())
|
||||
for filler in ['-', '∙']
|
||||
exec 'set fillchars+=stl:'..filler
|
||||
set statusline=%-5(x%),%-5.(x%),%-5.5(x%),%-5.10(x%);
|
||||
call assert_match(substitute('^x____,x____,x____,x____;_*$', '_', filler, 'g'), s:get_statusline())
|
||||
set statusline=%5(x%),%5.(x%),%5.5(x%),%5.10(x%);
|
||||
call assert_match(substitute('^____x,____x,____x,____x;_*$', '_', filler, 'g'), s:get_statusline())
|
||||
set statusline=%.5(12🙂345%),%4.5(12🙂345%),%5.5(12🙂345%),%50.5(12🙂345%);
|
||||
call assert_match(substitute('^<345,<345,<345_,<345_;_*$', '_', filler, 'g'), s:get_statusline())
|
||||
endfor
|
||||
if has('linux')
|
||||
" This assumes MAXPATHL is 4096 bytes.
|
||||
set stl=%{%repeat('x',4096-6)%}%10(X%)
|
||||
set fillchars+=stl:-
|
||||
call assert_match('^<x\+----X$', s:get_statusline())
|
||||
set fillchars+=stl:∙
|
||||
call assert_match('^<x\+∙X$', s:get_statusline())
|
||||
endif
|
||||
set fillchars&
|
||||
|
||||
" %h: Help buffer flag, text is "[help]".
|
||||
" %H: Help buffer flag, text is ",HLP".
|
||||
|
||||
Reference in New Issue
Block a user