mirror of
https://github.com/macvim-dev/macvim.git
synced 2026-06-07 15:37:14 +02:00
patch 9.2.0569: out-of-bounds access in libvterm CSI 8 t resize
Problem: In the bundled libvterm the CSI 8 ; rows ; cols t sequence reaches
on_resize() without validating its arguments. Missing, zero or
negative dimensions cause a negative-size memmove() in
resize_buffer() and out-of-bounds accesses in set_lineinfo() and
DECALN, all reachable from output rendered in a terminal window
(Yukihiro Nakamura).
Solution: Reject missing, zero or negative dimensions before calling
on_resize(). Also clamp a negative cell width in on_text() as
hardening for the bundled libvterm.
Signed-off-by: Christian Brabandt <cb@256bit.org>
This commit is contained in:
@@ -420,6 +420,9 @@ static int on_text(const char bytes[], size_t len, void *user)
|
||||
width = this_width; // TODO: should be += ?
|
||||
}
|
||||
|
||||
if (width < 0)
|
||||
width = 0;
|
||||
|
||||
while(i < npoints && vterm_unicode_is_combining(codepoints[i]))
|
||||
i++;
|
||||
|
||||
@@ -1640,7 +1643,9 @@ static int on_csi(const char *leader, const long args[], int argcount, const cha
|
||||
case 0x74:
|
||||
switch(CSI_ARG(args[0])) {
|
||||
case 8: // CSI 8 ; rows ; cols t set size
|
||||
if (argcount == 3)
|
||||
if (argcount == 3 &&
|
||||
!CSI_ARG_IS_MISSING(args[1]) && !CSI_ARG_IS_MISSING(args[2]) &&
|
||||
CSI_ARG(args[1]) > 0 && CSI_ARG(args[2]) > 0)
|
||||
on_resize(CSI_ARG(args[1]), CSI_ARG(args[2]), state);
|
||||
break;
|
||||
default:
|
||||
|
||||
@@ -1256,4 +1256,65 @@ func Test_terminal_output_combining_chars()
|
||||
bw!
|
||||
endfunc
|
||||
|
||||
" This caused a Crash
|
||||
func Test_terminal_csi_resize_oob()
|
||||
return
|
||||
CheckUnix
|
||||
CheckExecutable printf
|
||||
|
||||
" CSI 8 ; rows ; cols t with missing, zero or negative dimensions reached
|
||||
" on_resize()/resize_buffer() unvalidated, causing a negative-size memmove()
|
||||
" and out-of-bounds set_lineinfo()/DECALN accesses in libvterm. Rendering
|
||||
" these must not crash Vim.
|
||||
|
||||
" Sequences:
|
||||
" 1 resize_buffer negative-size memmove
|
||||
" 2 set_lineinfo OOB after corrupt resize
|
||||
" 3 DECALN putglyph OOB after corrupt resize
|
||||
let seqs = ["\<ESC>[8;0;t",
|
||||
\ "\<ESC>[8;;t\<ESC>[J",
|
||||
\ "\<ESC>[8;;0t\<ESC>#8"]
|
||||
|
||||
for seq in seqs
|
||||
let buf = term_start([&shell, &shellcmdflag, 'printf "%s" ' .. shellescape(seq)],
|
||||
\ #{term_rows: 10, term_cols: 40})
|
||||
call TermWait(buf)
|
||||
" Getting here without a crash (and no ASAN report) is the test.
|
||||
call assert_true(bufexists(buf))
|
||||
exe 'bwipe! ' .. buf
|
||||
endfor
|
||||
endfunc
|
||||
|
||||
" This caused a Crash, but Vim builds libvterm using -DWCWIDTH_FUNCTION=utf_uint2cells
|
||||
" which wouldn't return -1 and therefore does not reproduce here
|
||||
func Test_terminal_negative_col_oob()
|
||||
CheckUnix
|
||||
CheckExecutable printf
|
||||
|
||||
" A wcwidth() == -1 codepoint (U+0087, \302\207 in UTF-8) drove
|
||||
" state->pos.col negative, then used as an array index in the tabstop
|
||||
" helpers and moverect_internal(). These are single-byte / single-bit
|
||||
" out-of-bounds accesses that do not crash a normal build, so this test
|
||||
" is only meaningful under a sanitizer build; otherwise it just confirms
|
||||
" Vim does not crash.
|
||||
|
||||
" Sequences:
|
||||
" 1. clear_col_tabstop OOB read
|
||||
" 2. is_col_tabstop OOB read
|
||||
" 3. set_col_tabstop OOB write (HTS)
|
||||
" 4. moverect_internal memmove (insert mode)
|
||||
|
||||
let seqs = ["\302\207\<ESC>[g",
|
||||
\ "\302\207\302\207\t",
|
||||
\ "\302\207\<ESC>H",
|
||||
\ "\<ESC>[4h\302\2070"]
|
||||
for seq in seqs
|
||||
let buf = term_start([&shell, &shellcmdflag, 'printf "%s" ' .. shellescape(seq)],
|
||||
\ #{term_rows: 10, term_cols: 40})
|
||||
call TermWait(buf)
|
||||
call assert_true(bufexists(buf))
|
||||
exe 'bwipe! ' .. buf
|
||||
endfor
|
||||
endfunc
|
||||
|
||||
" vim: shiftwidth=2 sts=2 expandtab
|
||||
|
||||
@@ -729,6 +729,8 @@ static char *(features[]) =
|
||||
|
||||
static int included_patches[] =
|
||||
{ /* Add new patch number below this line */
|
||||
/**/
|
||||
569,
|
||||
/**/
|
||||
568,
|
||||
/**/
|
||||
|
||||
Reference in New Issue
Block a user