Mercurial > vim
changeset 33150:cdc797578b8b v9.0.1857
patch 9.0.1857: [security] heap-use-after-free in is_qf_win()
Commit: https://github.com/vim/vim/commit/fc68299d436cf87453e432daa77b6d545df4d7ed
Author: Christian Brabandt <cb@256bit.org>
Date: Sun Sep 3 20:20:52 2023 +0200
patch 9.0.1857: [security] heap-use-after-free in is_qf_win()
Problem: heap-use-after-free in is_qf_win()
Solution: Check buffer is valid before accessing it
Signed-off-by: Christian Brabandt <cb@256bit.org>
author | Christian Brabandt <cb@256bit.org> |
---|---|
date | Sun, 03 Sep 2023 20:30:02 +0200 |
parents | f566f2aae66b |
children | b22a96ad8582 |
files | src/main.c src/quickfix.c src/testdir/crash/bt_quickfix_poc src/testdir/test_crash.vim src/version.c |
diffstat | 5 files changed, 40 insertions(+), 9 deletions(-) [+] |
line wrap: on
line diff
--- a/src/main.c +++ b/src/main.c @@ -1646,7 +1646,7 @@ getout(int exitval) next_tp = tp->tp_next; FOR_ALL_WINDOWS_IN_TAB(tp, wp) { - if (wp->w_buffer == NULL) + if (wp->w_buffer == NULL || !buf_valid(wp->w_buffer)) // Autocmd must have close the buffer already, skip. continue; buf = wp->w_buffer;
--- a/src/quickfix.c +++ b/src/quickfix.c @@ -4492,7 +4492,7 @@ is_qf_win(win_T *win, qf_info_T *qi) // set to NULL. // A window displaying a location list buffer will have the w_llist_ref // pointing to the location list. - if (bt_quickfix(win->w_buffer)) + if (buf_valid(win->w_buffer) && bt_quickfix(win->w_buffer)) if ((IS_QF_STACK(qi) && win->w_llist_ref == NULL) || (IS_LL_STACK(qi) && win->w_llist_ref == qi)) return TRUE;
new file mode 100644 --- /dev/null +++ b/src/testdir/crash/bt_quickfix_poc @@ -0,0 +1,9 @@ +comman!-narg=* Xexpr <mods>lex<args> +auto BufReadPre * exe"sn" ..expand("<abuf>") +fu Xautocmd_changelist() +cal writefile(['Xtestfile2:4:4'],'Xerr') + sil! edi Xerr +Xexpr 'Xtestfile:4:4' +endf +call Xautocmd_changelist() +call Xautocmd_changelist() \ No newline at end of file
--- a/src/testdir/test_crash.vim +++ b/src/testdir/test_crash.vim @@ -5,38 +5,58 @@ source screendump.vim CheckScreendump func Test_crash1() + if !executable('sh') + throw 'Skipped: sh not executable!' + endif " The following used to crash Vim - " let opts = #{wait_for_ruler: 0, rows: 20, cmd: 'sh'} let opts = #{cmd: 'sh'} - let args = 'bash' let vim = GetVimProg() - let buf = RunVimInTerminal(args, opts) + let buf = RunVimInTerminal('sh', opts) let file = 'crash/poc_huaf1' let cmn_args = "%s -u NONE -i NONE -n -e -s -S %s -c ':qa!'" let args = printf(cmn_args, vim, file) call term_sendkeys(buf, args .. - \ ' && echo "crash 1: [OK]" >> X_crash1_result.txt' .. "\<cr>") + \ ' && echo "crash 1: [OK]" > X_crash1_result.txt' .. "\<cr>") + call TermWait(buf, 50) let file = 'crash/poc_huaf2' let args = printf(cmn_args, vim, file) call term_sendkeys(buf, args .. \ ' && echo "crash 2: [OK]" >> X_crash1_result.txt' .. "\<cr>") + call TermWait(buf, 50) let file = 'crash/poc_huaf3' let args = printf(cmn_args, vim, file) call term_sendkeys(buf, args .. \ ' && echo "crash 3: [OK]" >> X_crash1_result.txt' .. "\<cr>") + call TermWait(buf, 100) - call TermWait(buf, 50) + let file = 'crash/bt_quickfix_poc' + let args = printf(cmn_args, vim, file) + call term_sendkeys(buf, args .. + \ ' && echo "crash 4: [OK]" >> X_crash1_result.txt' .. "\<cr>") + " clean up + call delete('Xerr') + + " This test takes a bit longer + call TermWait(buf, 200) " clean up + call delete('Xerr') exe buf .. "bw!" sp X_crash1_result.txt - call assert_equal(['crash 1: [OK]', 'crash 2: [OK]', 'crash 3: [OK]'], - \ getline(1, '$')) + + let expected = [ + \ 'crash 1: [OK]', + \ 'crash 2: [OK]', + \ 'crash 3: [OK]', + \ 'crash 4: [OK]', + \ ] + + call assert_equal(expected, getline(1, '$')) bw! call delete('X_crash1_result.txt')