vim/backport-CVE-2022-3297.patch
wangjiang c4d4f93916 fix CVE-2022-3297
(cherry picked from commit 969bba7f01fe7ad131af32eddc10ea8a63d48e51)
2022-10-16 16:01:10 +08:00

138 lines
4.2 KiB
Diff
Raw Blame History

This file contains invisible Unicode characters

This file contains invisible Unicode characters that are indistinguishable to humans but may be processed differently by a computer. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

From 0ff01835a40f549c5c4a550502f62a2ac9ac447c Mon Sep 17 00:00:00 2001
From: Bram Moolenaar <Bram@vim.org>
Date: Sat, 24 Sep 2022 19:20:30 +0100
Subject: [PATCH] patch 9.0.0579: using freed memory when 'tagfunc' wipes out
buffer
Problem: Using freed memory when 'tagfunc' wipes out buffer that holds
'complete'.
Solution: Make a copy of the option. Make sure cursor position is valid.
---
src/insexpand.c | 39 +++++++++++++++++++++++++++----
src/move.c | 1 +
src/testdir/test_ins_complete.vim | 16 +++++++++++++
3 files changed, 51 insertions(+), 5 deletions(-)
diff --git a/src/insexpand.c b/src/insexpand.c
index a23d2d6..647297d 100644
--- a/src/insexpand.c
+++ b/src/insexpand.c
@@ -2210,7 +2210,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)
@@ -2672,6 +2673,7 @@ 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_copy = (char_u *)""; // copy of 'complete'
static int found_all = FALSE; // Found all matches of a
// certain type.
static buf_T *ins_buf = NULL; // buffer being scanned
@@ -2690,15 +2692,34 @@ ins_compl_get_exp(pos_T *ini)
char_u *dict = NULL;
int dict_f = 0;
int set_match_pos;
+ static int st_cleared = FALSE;
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)
+ {
+ e_cpt = NULL;
+ e_cpt_copy = NULL;
+ ins_buf = NULL;
+ set_match_pos = 0;
+ vim_memset(&first_match_pos, 0, sizeof(first_match_pos));
+ vim_memset(&last_match_pos, 0, sizeof(last_match_pos));
+ found_all = FALSE;
+ dict = NULL;
+ dict_f = 0;
+ 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))
@@ -3204,6 +3225,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.
@@ -3336,6 +3358,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 10165ef..1d7bcfb 100644
--- a/src/move.c
+++ b/src/move.c
@@ -637,6 +637,7 @@ cursor_valid(void)
void
validate_cursor(void)
{
+ check_cursor();
check_cursor_moved(curwin);
if ((curwin->w_valid & (VALID_WCOL|VALID_WROW)) != (VALID_WCOL|VALID_WROW))
curs_columns(TRUE);
diff --git a/src/testdir/test_ins_complete.vim b/src/testdir/test_ins_complete.vim
index 39ece18..1b53987 100644
--- a/src/testdir/test_ins_complete.vim
+++ b/src/testdir/test_ins_complete.vim
@@ -427,3 +427,19 @@ func Test_ins_complete_end_of_line()
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
--
2.33.0