RHEL-2159 vim: Heap Use After Free in function ins_compl_get_exp in vim/vim
Resolves: RHEL-2159
This commit is contained in:
parent
2bba9e8166
commit
99204e95ee
262
vim-CVE-2023-4752.patch
Normal file
262
vim-CVE-2023-4752.patch
Normal file
@ -0,0 +1,262 @@
|
|||||||
|
diff --git a/src/insexpand.c b/src/insexpand.c
|
||||||
|
index 8d76c68..2ce675d 100644
|
||||||
|
--- a/src/insexpand.c
|
||||||
|
+++ b/src/insexpand.c
|
||||||
|
@@ -2162,7 +2162,8 @@ ins_compl_next_buf(buf_T *buf, int flag)
|
||||||
|
|
||||||
|
if (flag == 'w') // just windows
|
||||||
|
{
|
||||||
|
- if (buf == curbuf || wp == NULL) // first call for this flag/expansion
|
||||||
|
+ if (buf == curbuf || !win_valid(wp))
|
||||||
|
+ // first call for this flag/expansion or window was closed
|
||||||
|
wp = curwin;
|
||||||
|
while ((wp = (wp->w_next != NULL ? wp->w_next : firstwin)) != curwin
|
||||||
|
&& wp->w_buffer->b_scanned)
|
||||||
|
@@ -2675,10 +2676,12 @@ ins_compl_get_exp(pos_T *ini)
|
||||||
|
{
|
||||||
|
static pos_T first_match_pos;
|
||||||
|
static pos_T last_match_pos;
|
||||||
|
- static char_u *e_cpt = (char_u *)""; // curr. entry in 'complete'
|
||||||
|
+ static char_u *e_cpt; // curr. entry in 'complete'
|
||||||
|
+ static char_u *e_cpt_copy; // copy of curr. entry in 'complete'
|
||||||
|
static int found_all = FALSE; // Found all matches of a
|
||||||
|
// certain type.
|
||||||
|
static buf_T *ins_buf = NULL; // buffer being scanned
|
||||||
|
+ static int st_cleared = FALSE;
|
||||||
|
|
||||||
|
pos_T *pos;
|
||||||
|
char_u **matches;
|
||||||
|
@@ -2697,12 +2700,34 @@ ins_compl_get_exp(pos_T *ini)
|
||||||
|
|
||||||
|
if (!compl_started)
|
||||||
|
{
|
||||||
|
- FOR_ALL_BUFFERS(ins_buf)
|
||||||
|
- ins_buf->b_scanned = 0;
|
||||||
|
+ buf_T *buf;
|
||||||
|
+
|
||||||
|
+ FOR_ALL_BUFFERS(buf)
|
||||||
|
+ buf->b_scanned = 0;
|
||||||
|
+ if (!st_cleared)
|
||||||
|
+ {
|
||||||
|
+ // this code does not match upstream commit, upstream clears struct `st`
|
||||||
|
+ // which includes the members which are arguments of `CLEAR_FIELD()` macros
|
||||||
|
+ // below. The code below should do the same thing as upstream `CLEAR_FIELD(st)`
|
||||||
|
+ CLEAR_FIELD(e_cpt);
|
||||||
|
+ CLEAR_FIELD(e_cpt_copy);
|
||||||
|
+ CLEAR_FIELD(ins_buf);
|
||||||
|
+ CLEAR_FIELD(pos);
|
||||||
|
+ CLEAR_FIELD(set_match_pos);
|
||||||
|
+ CLEAR_FIELD(first_match_pos);
|
||||||
|
+ CLEAR_FIELD(last_match_pos);
|
||||||
|
+ CLEAR_FIELD(found_all);
|
||||||
|
+ CLEAR_FIELD(dict);
|
||||||
|
+ CLEAR_FIELD(dict_f);
|
||||||
|
+ st_cleared = TRUE;
|
||||||
|
+ }
|
||||||
|
found_all = FALSE;
|
||||||
|
ins_buf = curbuf;
|
||||||
|
- e_cpt = (compl_cont_status & CONT_LOCAL)
|
||||||
|
- ? (char_u *)"." : curbuf->b_p_cpt;
|
||||||
|
+ vim_free(e_cpt_copy);
|
||||||
|
+ // Make a copy of 'complete', if case the buffer is wiped out.
|
||||||
|
+ e_cpt_copy = vim_strsave((compl_cont_status & CONT_LOCAL)
|
||||||
|
+ ? (char_u *)"." : curbuf->b_p_cpt);
|
||||||
|
+ e_cpt = e_cpt_copy == NULL ? (char_u *)"" : e_cpt_copy;
|
||||||
|
last_match_pos = first_match_pos = *ini;
|
||||||
|
}
|
||||||
|
else if (ins_buf != curbuf && !buf_valid(ins_buf))
|
||||||
|
@@ -3100,7 +3125,7 @@ ins_compl_get_exp(pos_T *ini)
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// Mark a buffer scanned when it has been scanned completely
|
||||||
|
- if (type == 0 || type == CTRL_X_PATH_PATTERNS)
|
||||||
|
+ if (buf_valid(ins_buf) && (type == 0 || type == CTRL_X_PATH_PATTERNS))
|
||||||
|
ins_buf->b_scanned = TRUE;
|
||||||
|
|
||||||
|
compl_started = FALSE;
|
||||||
|
@@ -3210,6 +3235,7 @@ ins_compl_next(
|
||||||
|
int found_end = FALSE;
|
||||||
|
int advance;
|
||||||
|
int started = compl_started;
|
||||||
|
+ buf_T *orig_curbuf = curbuf;
|
||||||
|
|
||||||
|
// When user complete function return -1 for findstart which is next
|
||||||
|
// time of 'always', compl_shown_match become NULL.
|
||||||
|
@@ -3342,6 +3368,13 @@ ins_compl_next(
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
+ if (curbuf != orig_curbuf)
|
||||||
|
+ {
|
||||||
|
+ // In case some completion function switched buffer, don't want to
|
||||||
|
+ // insert the completion elsewhere.
|
||||||
|
+ return -1;
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
// Insert the text of the new completion, or the compl_leader.
|
||||||
|
if (compl_no_insert && !started)
|
||||||
|
{
|
||||||
|
diff --git a/src/move.c b/src/move.c
|
||||||
|
index 8ac1d0e..55cbd24 100644
|
||||||
|
--- a/src/move.c
|
||||||
|
+++ b/src/move.c
|
||||||
|
@@ -649,6 +649,7 @@ cursor_valid(void)
|
||||||
|
void
|
||||||
|
validate_cursor(void)
|
||||||
|
{
|
||||||
|
+ check_cursor_lnum();
|
||||||
|
check_cursor_moved(curwin);
|
||||||
|
if ((curwin->w_valid & (VALID_WCOL|VALID_WROW)) != (VALID_WCOL|VALID_WROW))
|
||||||
|
curs_columns(TRUE);
|
||||||
|
diff --git a/src/testdir/Make_all.mak b/src/testdir/Make_all.mak
|
||||||
|
index 108c528..e800864 100644
|
||||||
|
--- a/src/testdir/Make_all.mak
|
||||||
|
+++ b/src/testdir/Make_all.mak
|
||||||
|
@@ -92,6 +92,7 @@ NEW_TESTS = \
|
||||||
|
test_conceal \
|
||||||
|
test_const \
|
||||||
|
test_cpoptions \
|
||||||
|
+ test_crash \
|
||||||
|
test_crypt \
|
||||||
|
test_cscope \
|
||||||
|
test_cursor_func \
|
||||||
|
@@ -348,6 +349,7 @@ NEW_TESTS_RES = \
|
||||||
|
test_conceal.res \
|
||||||
|
test_const.res \
|
||||||
|
test_cpoptions.res \
|
||||||
|
+ test_crash.res \
|
||||||
|
test_crypt.res \
|
||||||
|
test_cscope.res \
|
||||||
|
test_cursor_func.res \
|
||||||
|
diff --git a/src/testdir/crash/poc_tagfunc.vim b/src/testdir/crash/poc_tagfunc.vim
|
||||||
|
new file mode 100644
|
||||||
|
index 0000000..49d9b6f
|
||||||
|
--- /dev/null
|
||||||
|
+++ b/src/testdir/crash/poc_tagfunc.vim
|
||||||
|
@@ -0,0 +1,6 @@
|
||||||
|
+fu Tagfunc(t,f,o)
|
||||||
|
+ bw
|
||||||
|
+endf
|
||||||
|
+set tagfunc=Tagfunc
|
||||||
|
+n0
|
||||||
|
+sil0norm0i
|
||||||
|
diff --git a/src/testdir/term_util.vim b/src/testdir/term_util.vim
|
||||||
|
index 8541ef3..3a06019 100644
|
||||||
|
--- a/src/testdir/term_util.vim
|
||||||
|
+++ b/src/testdir/term_util.vim
|
||||||
|
@@ -54,6 +54,7 @@ endfunc
|
||||||
|
" "cols" - width of the terminal window (max. 78)
|
||||||
|
" "statusoff" - number of lines the status is offset from default
|
||||||
|
" "wait_for_ruler" - if zero then don't wait for ruler to show
|
||||||
|
+" "cmd" - run any other command, e.g. "xxd" (used in xxd test)
|
||||||
|
func RunVimInTerminal(arguments, options)
|
||||||
|
" If Vim doesn't exit a swap file remains, causing other tests to fail.
|
||||||
|
" Remove it here.
|
||||||
|
@@ -88,7 +89,11 @@ func RunVimInTerminal(arguments, options)
|
||||||
|
let reset_u7 = ' --cmd "set t_u7=" '
|
||||||
|
endif
|
||||||
|
|
||||||
|
- let cmd = GetVimCommandCleanTerm() .. reset_u7 .. a:arguments
|
||||||
|
+ if empty(get(a:options, 'cmd', ''))
|
||||||
|
+ let cmd = GetVimCommandCleanTerm() .. reset_u7 .. a:arguments
|
||||||
|
+ else
|
||||||
|
+ let cmd = get(a:options, 'cmd')
|
||||||
|
+ endif
|
||||||
|
|
||||||
|
let options = #{curwin: 1}
|
||||||
|
if &termwinsize == ''
|
||||||
|
@@ -114,7 +119,7 @@ func RunVimInTerminal(arguments, options)
|
||||||
|
|
||||||
|
call TermWait(buf)
|
||||||
|
|
||||||
|
- if get(a:options, 'wait_for_ruler', 1)
|
||||||
|
+ if get(a:options, 'wait_for_ruler', 1) && empty(get(a:options, 'cmd', ''))
|
||||||
|
" Wait for "All" or "Top" of the ruler to be shown in the last line or in
|
||||||
|
" the status line of the last window. This can be quite slow (e.g. when
|
||||||
|
" using valgrind).
|
||||||
|
diff --git a/src/testdir/test_crash.vim b/src/testdir/test_crash.vim
|
||||||
|
new file mode 100644
|
||||||
|
index 0000000..4be1b49
|
||||||
|
--- /dev/null
|
||||||
|
+++ b/src/testdir/test_crash.vim
|
||||||
|
@@ -0,0 +1,40 @@
|
||||||
|
+" Some tests, that used to crash Vim
|
||||||
|
+source check.vim
|
||||||
|
+source screendump.vim
|
||||||
|
+
|
||||||
|
+CheckScreendump
|
||||||
|
+
|
||||||
|
+func Test_crash1()
|
||||||
|
+ if !executable('sh')
|
||||||
|
+ throw 'Skipped: sh not executable!'
|
||||||
|
+ endif
|
||||||
|
+ " The following used to crash Vim
|
||||||
|
+ let opts = #{cmd: 'sh'}
|
||||||
|
+ let vim = GetVimProg()
|
||||||
|
+
|
||||||
|
+ let buf = RunVimInTerminal('sh', opts)
|
||||||
|
+
|
||||||
|
+ let file = 'crash/poc_tagfunc.vim'
|
||||||
|
+ 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 5: [OK]" >> X_crash1_result.txt' .. "\<cr>")
|
||||||
|
+
|
||||||
|
+ call TermWait(buf, 100)
|
||||||
|
+
|
||||||
|
+ " clean up
|
||||||
|
+ exe buf .. "bw!"
|
||||||
|
+
|
||||||
|
+ sp X_crash1_result.txt
|
||||||
|
+
|
||||||
|
+ let expected = [
|
||||||
|
+ \ 'crash 5: [OK]',
|
||||||
|
+ \ ]
|
||||||
|
+
|
||||||
|
+ call assert_equal(expected, getline(1, '$'))
|
||||||
|
+ bw!
|
||||||
|
+
|
||||||
|
+ call delete('X_crash1_result.txt')
|
||||||
|
+endfunc
|
||||||
|
+
|
||||||
|
+" vim: shiftwidth=2 sts=2 expandtab
|
||||||
|
diff --git a/src/testdir/test_ins_complete.vim b/src/testdir/test_ins_complete.vim
|
||||||
|
index 613e952..24232d8 100644
|
||||||
|
--- a/src/testdir/test_ins_complete.vim
|
||||||
|
+++ b/src/testdir/test_ins_complete.vim
|
||||||
|
@@ -496,9 +496,8 @@ func Test_pum_with_preview_win()
|
||||||
|
|
||||||
|
call writefile(lines, 'Xpreviewscript')
|
||||||
|
let buf = RunVimInTerminal('-S Xpreviewscript', #{rows: 12})
|
||||||
|
- call TermWait(buf, 50)
|
||||||
|
call term_sendkeys(buf, "Gi\<C-X>\<C-O>")
|
||||||
|
- call TermWait(buf, 100)
|
||||||
|
+ call TermWait(buf, 200)
|
||||||
|
call term_sendkeys(buf, "\<C-N>")
|
||||||
|
call VerifyScreenDump(buf, 'Test_pum_with_preview_win', {})
|
||||||
|
|
||||||
|
@@ -724,7 +723,23 @@ func Test_z1_complete_no_history()
|
||||||
|
exe "normal owh\<C-X>\<C-K>"
|
||||||
|
exe "normal owh\<C-N>"
|
||||||
|
call assert_equal(currmess, execute('messages'))
|
||||||
|
- close!
|
||||||
|
+ bwipe!
|
||||||
|
+endfunc
|
||||||
|
+
|
||||||
|
+func s:Tagfunc(t,f,o)
|
||||||
|
+ bwipe!
|
||||||
|
+ return []
|
||||||
|
+endfunc
|
||||||
|
+
|
||||||
|
+" This was using freed memory, since 'complete' was in a wiped out buffer.
|
||||||
|
+" Also using a window that was closed.
|
||||||
|
+func Test_tagfunc_wipes_out_buffer()
|
||||||
|
+ new
|
||||||
|
+ set complete=.,t,w,b,u,i
|
||||||
|
+ se tagfunc=s:Tagfunc
|
||||||
|
+ sil norm i␎
|
||||||
|
+ bwipe!
|
||||||
|
endfunc
|
||||||
|
|
||||||
|
+
|
||||||
|
" vim: shiftwidth=2 sts=2 expandtab
|
15
vim.spec
15
vim.spec
@ -27,7 +27,7 @@ Summary: The VIM editor
|
|||||||
URL: http://www.vim.org/
|
URL: http://www.vim.org/
|
||||||
Name: vim
|
Name: vim
|
||||||
Version: %{baseversion}.%{patchlevel}
|
Version: %{baseversion}.%{patchlevel}
|
||||||
Release: 21%{?dist}
|
Release: 22%{?dist}
|
||||||
License: Vim and MIT
|
License: Vim and MIT
|
||||||
Source0: ftp://ftp.vim.org/pub/vim/unix/vim-%{baseversion}-%{patchlevel}.tar.bz2
|
Source0: ftp://ftp.vim.org/pub/vim/unix/vim-%{baseversion}-%{patchlevel}.tar.bz2
|
||||||
Source1: virc
|
Source1: virc
|
||||||
@ -138,6 +138,15 @@ Patch3052: 0001-patch-8.2.5037-cursor-position-may-be-invalid-after-.patch
|
|||||||
Patch3053:0001-patch-9.0.0339-no-check-if-the-return-value-of-XChan.patch
|
Patch3053:0001-patch-9.0.0339-no-check-if-the-return-value-of-XChan.patch
|
||||||
# RHEL-40602 CVE-2021-3903 vim: heap-based buffer overflow vulnerability
|
# RHEL-40602 CVE-2021-3903 vim: heap-based buffer overflow vulnerability
|
||||||
Patch3054: 0001-patch-8.2.3564-invalid-memory-access-when-scrolling-.patch
|
Patch3054: 0001-patch-8.2.3564-invalid-memory-access-when-scrolling-.patch
|
||||||
|
# RHEL-2159 vim: Heap Use After Free in function ins_compl_get_exp in vim/vim
|
||||||
|
# combined patch of some parts of the following commits:
|
||||||
|
# https://github.com/vim/vim/commit/e1dc9a6275
|
||||||
|
# https://github.com/vim/vim/commit/ee9166eb3b
|
||||||
|
# https://github.com/vim/vim/commit/0ff01835a4
|
||||||
|
# https://github.com/vim/vim/commit/d4566c14e7
|
||||||
|
# https://github.com/vim/vim/commit/d979d64fa2
|
||||||
|
# https://github.com/vim/vim/commit/e2528ae111
|
||||||
|
Patch3055: vim-CVE-2023-4752.patch
|
||||||
|
|
||||||
# gcc is no longer in buildroot by default
|
# gcc is no longer in buildroot by default
|
||||||
BuildRequires: gcc
|
BuildRequires: gcc
|
||||||
@ -379,6 +388,7 @@ perl -pi -e "s,bin/nawk,bin/awk,g" runtime/tools/mve.awk
|
|||||||
%patch3052 -p1 -b .cve1927
|
%patch3052 -p1 -b .cve1927
|
||||||
%patch3053 -p1 -b .cve47024
|
%patch3053 -p1 -b .cve47024
|
||||||
%patch -P 3054 -p1 -b .cve2021-3903
|
%patch -P 3054 -p1 -b .cve2021-3903
|
||||||
|
%patch -P 3055 -p1 -b .CVE-2023-4752
|
||||||
|
|
||||||
%build
|
%build
|
||||||
cd src
|
cd src
|
||||||
@ -936,6 +946,9 @@ touch %{buildroot}/%{_datadir}/%{name}/vimfiles/doc/tags
|
|||||||
%endif
|
%endif
|
||||||
|
|
||||||
%changelog
|
%changelog
|
||||||
|
* Tue Feb 25 2025 Zdenek Dohnal <zdohnal@redhat.com> - 2:8.2.2637-22
|
||||||
|
- RHEL-2159 vim: Heap Use After Free in function ins_compl_get_exp in vim/vim
|
||||||
|
|
||||||
* Mon Aug 05 2024 Zdenek Dohnal <zdohnal@redhat.com> - 2:8.2.2637-21
|
* Mon Aug 05 2024 Zdenek Dohnal <zdohnal@redhat.com> - 2:8.2.2637-21
|
||||||
- RHEL-40602 CVE-2021-3903 vim: heap-based buffer overflow vulnerability
|
- RHEL-40602 CVE-2021-3903 vim: heap-based buffer overflow vulnerability
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user