CVE-2022-3324: Stack-based Buffer Overflow (CWE-121)
value: Stack-based Buffer Overflow in GitHub repository vim/vim prior to 9.0.0598.
CWE description: A stack-based buffer overflow condition is a condition where the buffer being overwritten is allocated on the stack (i.e., is a local variable or, rarely, a parameter to a function).
CVSS v3 base score: 7.8
Published: 2022-09-27T23:15Z
Repository: https://github.com/vim/vim
Language: C
Files changed: src/testdir/test_cmdwin.vim, src/version.c, src/window.c
Commit date: 2022-09-26 23:08:22 +0100
Commit message: patch 9.0.0598: using negative array index with negative width window

Problem:    Using negative array index with negative width window.
Solution:   Make sure the window width does not become negative.

Diff: diff --git a/src/testdir/test_cmdwin.vim b/src/testdir/test_cmdwin.vim
index 6a420ed0aaa3..dc6889495f7c 100644
--- a/src/testdir/test_cmdwin.vim
+++ b/src/testdir/test_cmdwin.vim
@@ -402,7 +402,29 @@ func Test_cmdwin_freed_buffer_ptr()
 
   au! BufEnter
   bwipe!
 endfunc
 
+" This was resulting in a window with negative width.
+" The test doesn't reproduce the illegal memory access though...
+func Test_cmdwin_split_often()
+  let lines = &lines
+  let columns = &columns
+  set t_WS=
+
+  try
+    set encoding=iso8859
+    set ruler
+    winsize 0 0
+    noremap 0 H
+    sil norm 0000000q:
+  catch /E36:/
+  endtry
+
+  bwipe!
+  set encoding=utf8
+  let &lines = lines
+  let &columns = columns
+endfunc
+
 
 " vim: shiftwidth=2 sts=2 expandtab
diff --git a/src/version.c b/src/version.c
index d6535b3928a6..515be0b9a817 100644
--- a/src/version.c
+++ b/src/version.c
@@ -697,10 +697,12 @@ static char *(features[]) =
 	NULL
 };
 
 static int included_patches[] =
 {   /* Add new patch number below this line */
+/**/
+    598,
 /**/
     597,
 /**/
     596,
 /**/
diff --git a/src/window.c b/src/window.c
index 755848e43c08..db08e41326df 100644
--- a/src/window.c
+++ b/src/window.c
@@ -2087,10 +2087,12 @@ win_equal_rec(
 		    new_size = (wincount * room + ((unsigned)totwincount >> 1))
 								/ totwincount;
 		if (hnc)	    // add next_curwin size
 		{
 		    next_curwin_size -= p_wiw - (m - n);
+		    if (next_curwin_size < 0)
+			next_curwin_size = 0;
 		    new_size += next_curwin_size;
 		    room -= new_size - next_curwin_size;
 		}
 		else
 		    room -= new_size;
@@ -6609,11 +6611,12 @@ scroll_to_fraction(win_T *wp, int prev_height)
  * Set the width of a window.
  */
     void
 win_new_width(win_T *wp, int width)
 {
-    wp->w_width = width;
+    // Should we give an error if width < 0?
+    wp->w_width = width < 0 ? 0 : width;
     wp->w_lines_valid = 0;
     changed_line_abv_curs_win(wp);
     // Handled in win_fix_scroll()
     if (p_spsc)
     {

Vulnerable code:     wp->w_width = width;
Fixed code: " This was resulting in a window with negative width.
" The test doesn't reproduce the illegal memory access though...
func Test_cmdwin_split_often()
  let lines = &lines
  let columns = &columns
  set t_WS=

  try
    set encoding=iso8859
    set ruler
    winsize 0 0
    noremap 0 H
    sil norm 0000000q:
  catch /E36:/
  endtry

  bwipe!
  set encoding=utf8
  let &lines = lines
  let &columns = columns
endfunc

/**/
    598,
		    if (next_curwin_size < 0)
			next_curwin_size = 0;
    // Should we give an error if width < 0?
    wp->w_width = width < 0 ? 0 : width;