Publicus/cvefixes-security-ir-graphrag huggingface dataset:
CVE-2022-2129: Out-of-bounds Write (CWE-787)
value: Out-of-bounds Write in GitHub repository vim/vim prior to 8.2.
CWE description: The product writes data past the end, or before the beginning, of the intended buffer.
CVSS v3 base score: 7.8
Published: 2022-06-19T19:15Z
Repository: https://github.com/vim/vim
Language: C
Files changed: src/ex_docmd.c, src/testdir/test_substitute.vim, src/version.c
Commit date: 2022-06-18 19:48:14 +0100
Commit message: patch 8.2.5126: substitute may overrun destination buffer

Problem:    Substitute may overrun destination buffer.
Solution:   Disallow switching buffers in a substitute expression.

Diff: diff --git a/src/ex_docmd.c b/src/ex_docmd.c
index fed9330b52e..1185cd1550a 100644
--- a/src/ex_docmd.c
+++ b/src/ex_docmd.c
@@ -7136,13 +7136,14 @@ do_exedit(
 #ifdef FEAT_BROWSE
 	    || (cmdmod.cmod_flags & CMOD_BROWSE)
 #endif
 	    )
     {
-	// Can't edit another file when "curbuf_lock" is set.  Only ":edit"
-	// can bring us here, others are stopped earlier.
-	if (*eap->arg != NUL && curbuf_locked())
+	// Can't edit another file when "textlock" or "curbuf_lock" is set.
+	// Only ":edit" or ":script" can bring us here, others are stopped
+	// earlier.
+	if (*eap->arg != NUL && text_or_buf_locked())
 	    return;
 
 	n = readonlymode;
 	if (eap->cmdidx == CMD_view || eap->cmdidx == CMD_sview)
 	    readonlymode = TRUE;
diff --git a/src/testdir/test_substitute.vim b/src/testdir/test_substitute.vim
index 46ea9551319..c056fa96569 100644
--- a/src/testdir/test_substitute.vim
+++ b/src/testdir/test_substitute.vim
@@ -1061,10 +1061,23 @@ func Test_sub_open_cmdline_win()
 
   call delete('Xscript')
   call delete('Xresult')
 endfunc
 
+" This was editing a script file from the expression
+func Test_sub_edit_scriptfile()
+  new
+  norm o0000000000000000000000000000000000000000000000000000
+  func EditScript()
+    silent! scr! Xfile
+  endfunc
+  s/\%')/\=EditScript()
+
+  delfunc EditScript
+  bwipe!
+endfunc
+
 " Test for the 2-letter and 3-letter :substitute commands
 func Test_substitute_short_cmd()
   new
   call setline(1, ['one', 'one one one'])
   s/one/two
diff --git a/src/version.c b/src/version.c
index 82ac4eaf2dd..2f397ae315f 100644
--- a/src/version.c
+++ b/src/version.c
@@ -732,10 +732,12 @@ static char *(features[]) =
 	NULL
 };
 
 static int included_patches[] =
 {   /* Add new patch number below this line */
+/**/
+    5126,
 /**/
     5125,
 /**/
     5124,
 /**/

Vulnerable code: 	// Can't edit another file when "curbuf_lock" is set.  Only ":edit"
	// can bring us here, others are stopped earlier.
	if (*eap->arg != NUL && curbuf_locked())
Fixed code: 	// Can't edit another file when "textlock" or "curbuf_lock" is set.
	// Only ":edit" or ":script" can bring us here, others are stopped
	// earlier.
	if (*eap->arg != NUL && text_or_buf_locked())
" This was editing a script file from the expression
func Test_sub_edit_scriptfile()
  new
  norm o0000000000000000000000000000000000000000000000000000
  func EditScript()
    silent! scr! Xfile
  endfunc
  s/\%')/\=EditScript()

  delfunc EditScript
  bwipe!
endfunc

/**/
    5126,
CVE-2022-2175: Out-of-bounds Read (CWE-125)
value: Buffer Over-read in GitHub repository vim/vim prior to 8.2.
CWE description: The product reads data past the end, or before the beginning, of the intended buffer.
CVSS v3 base score: 7.8
Published: 2022-06-23T13:15Z
Repository: https://github.com/vim/vim
Language: C
Files changed: src/ex_getln.c, src/testdir/test_cmdline.vim, src/version.c
Commit date: 2022-06-22 13:51:54 +0100
Commit message: patch 8.2.5148: invalid memory access when using expression on command line

Problem:    Invalid memory access when using an expression on the command line.
Solution:   Make sure the position does not go negative.

Diff: diff --git a/src/ex_getln.c b/src/ex_getln.c
index af4dc19be19..b499aba141b 100644
--- a/src/ex_getln.c
+++ b/src/ex_getln.c
@@ -1204,10 +1204,11 @@ cmdline_toggle_langmap(long *b_im_ptr)
     static int
 cmdline_insert_reg(int *gotesc UNUSED)
 {
     int		i;
     int		c;
+    int		save_new_cmdpos = new_cmdpos;
 
 #ifdef USE_ON_FLY_SCROLL
     dont_scroll = TRUE;	// disallow scrolling here
 #endif
     putcmdline('"', TRUE);
@@ -1222,12 +1223,10 @@ cmdline_insert_reg(int *gotesc UNUSED)
     --no_mapping;
     --allow_keys;
 #ifdef FEAT_EVAL
     /*
      * Insert the result of an expression.
-     * Need to save the current command line, to be able to enter
-     * a new one...
      */
     new_cmdpos = -1;
     if (c == '=')
     {
 	if (ccline.cmdfirstc == '='  // can't do this recursively
@@ -1264,10 +1263,12 @@ cmdline_insert_reg(int *gotesc UNUSED)
 	    else
 		ccline.cmdpos = new_cmdpos;
 	}
 #endif
     }
+    new_cmdpos = save_new_cmdpos;
+
     // remove the double quote
     redrawcmd();
 
     // The text has been stuffed, the command line didn't change yet.
     return CMDLINE_NOT_CHANGED;
diff --git a/src/testdir/test_cmdline.vim b/src/testdir/test_cmdline.vim
index 2289c343e9f..9c08d138042 100644
--- a/src/testdir/test_cmdline.vim
+++ b/src/testdir/test_cmdline.vim
@@ -1985,10 +1985,15 @@ func Test_cmdline_expr()
   " Insert literal <CTRL-\> in the command line
   call feedkeys(":\"e \<C-\>\<C-Y>\<CR>", 'xt')
   call assert_equal("\"e \<C-\>\<C-Y>", @:)
 endfunc
 
+" This was making the insert position negative
+func Test_cmdline_expr_register()
+  exe "sil! norm! ?\<C-\>e0\<C-R>0\<Esc>?\<C-\>e0\<CR>"
+endfunc
+
 " Test for 'imcmdline' and 'imsearch'
 " This test doesn't actually test the input method functionality.
 func Test_cmdline_inputmethod()
   new
   call setline(1, ['', 'abc', ''])
diff --git a/src/version.c b/src/version.c
index 35024fb5940..e567a3a9995 100644
--- a/src/version.c
+++ b/src/version.c
@@ -732,10 +732,12 @@ static char *(features[]) =
 	NULL
 };
 
 static int included_patches[] =
 {   /* Add new patch number below this line */
+/**/
+    5148,
 /**/
     5147,
 /**/
     5146,
 /**/

Vulnerable code:      * Need to save the current command line, to be able to enter
     * a new one...
Fixed code:     int		save_new_cmdpos = new_cmdpos;
    new_cmdpos = save_new_cmdpos;

" This was making the insert position negative
func Test_cmdline_expr_register()
  exe "sil! norm! ?\<C-\>e0\<C-R>0\<Esc>?\<C-\>e0\<CR>"
endfunc

/**/
    5148,
CVE-2022-2182: Heap-based Buffer Overflow (CWE-122)
value: Heap-based Buffer Overflow in GitHub repository vim/vim prior to 8.2.
CWE description: A heap overflow condition is a buffer overflow, where the buffer that can be overwritten is allocated in the heap portion of memory, generally meaning that the buffer was allocated using a routine such as malloc().
CVSS v3 base score: 7.8
Published: 2022-06-23T18:15Z
Repository: https://github.com/vim/vim
Language: C
Files changed: src/ex_docmd.c, src/testdir/test_cmdline.vim, src/version.c
Commit date: 2022-06-22 19:08:38 +0100
Commit message: patch 8.2.5150: read past the end of the first line with ":0;'{"

Problem:    Read past the end of the first line with ":0;'{".
Solution:   When on line zero check the column is valid for line one.

Diff: diff --git a/src/ex_docmd.c b/src/ex_docmd.c
index 1185cd1550a..271e7e24663 100644
--- a/src/ex_docmd.c
+++ b/src/ex_docmd.c
@@ -3409,14 +3409,17 @@ parse_cmd_address(exarg_T *eap, char **errormsg, int silent)
 	    if (!eap->skip)
 	    {
 		curwin->w_cursor.lnum = eap->line2;
 
 		// Don't leave the cursor on an illegal line or column, but do
-		// accept zero as address, so 0;/PATTERN/ works correctly.
+		// accept zero as address, so 0;/PATTERN/ works correctly
+		// (where zero usually means to use the first line).
 		// Check the cursor position before returning.
 		if (eap->line2 > 0)
 		    check_cursor();
+		else
+		    check_cursor_col();
 		need_check_cursor = TRUE;
 	    }
 	}
 	else if (*eap->cmd != ',')
 	    break;
diff --git a/src/testdir/test_cmdline.vim b/src/testdir/test_cmdline.vim
index 9c08d138042..36853369855 100644
--- a/src/testdir/test_cmdline.vim
+++ b/src/testdir/test_cmdline.vim
@@ -806,10 +806,18 @@ func Test_illegal_address2()
   quit!
   bwipe!
   call delete('Xtest.vim')
 endfunc
 
+func Test_mark_from_line_zero()
+  " this was reading past the end of the first (empty) line
+  new
+  norm oxxxx
+  call assert_fails("0;'(", 'E20:')
+  bwipe!
+endfunc
+
 func Test_cmdline_complete_wildoptions()
   help
   call feedkeys(":tag /\<c-a>\<c-b>\"\<cr>", 'tx')
   let a = join(sort(split(@:)),' ')
   set wildoptions=tagfile
diff --git a/src/version.c b/src/version.c
index 609c95559d3..b947061b3ff 100644
--- a/src/version.c
+++ b/src/version.c
@@ -732,10 +732,12 @@ static char *(features[]) =
 	NULL
 };
 
 static int included_patches[] =
 {   /* Add new patch number below this line */
+/**/
+    5150,
 /**/
     5149,
 /**/
     5148,
 /**/

Vulnerable code: 		// accept zero as address, so 0;/PATTERN/ works correctly.
Fixed code: 		// accept zero as address, so 0;/PATTERN/ works correctly
		// (where zero usually means to use the first line).
		else
		    check_cursor_col();
func Test_mark_from_line_zero()
  " this was reading past the end of the first (empty) line
  new
  norm oxxxx
  call assert_fails("0;'(", 'E20:')
  bwipe!
endfunc

/**/
    5150,
CVE-2022-2183: Out-of-bounds Read (CWE-125)
value: Out-of-bounds Read in GitHub repository vim/vim prior to 8.2.
CWE description: The product reads data past the end, or before the beginning, of the intended buffer.
CVSS v3 base score: 7.8
Published: 2022-06-23T19:15Z
Repository: https://github.com/vim/vim
Language: C
Files changed: src/indent.c, src/testdir/test_lispwords.vim, src/version.c
Commit date: 2022-06-22 19:59:28 +0100
Commit message: patch 8.2.5151: reading beyond the end of the line with lisp indenting

Problem:    Reading beyond the end of the line with lisp indenting.
Solution:   Avoid going over the NUL at the end of the line.

Diff: diff --git a/src/indent.c b/src/indent.c
index fa177bcf2c7..f6cfe4b2f82 100644
--- a/src/indent.c
+++ b/src/indent.c
@@ -2074,12 +2074,15 @@ get_lisp_indent(void)
 		if (!vi_lisp && (*that == '(' || *that == '[')
 						      && lisp_match(that + 1))
 		    amount += 2;
 		else
 		{
-		    that++;
-		    amount++;
+		    if (*that != NUL)
+		    {
+			that++;
+			amount++;
+		    }
 		    firsttry = amount;
 
 		    while (VIM_ISWHITE(*that))
 		    {
 			amount += lbr_chartabsize(line, that, (colnr_T)amount);
diff --git a/src/testdir/test_lispwords.vim b/src/testdir/test_lispwords.vim
index ff710b27163..4144fb05211 100644
--- a/src/testdir/test_lispwords.vim
+++ b/src/testdir/test_lispwords.vim
@@ -1,6 +1,7 @@
-" Tests for 'lispwords' settings being global-local
+" Tests for 'lispwords' settings being global-local.
+" And  other lisp indent stuff.
 
 set nocompatible viminfo+=nviminfo
 
 func Test_global_local_lispwords()
   setglobal lispwords=foo,bar,baz
@@ -83,6 +84,15 @@ func Test_lisp_indent()
   enew!
   let &cpoptions=save_copt
   set nolisp
 endfunc
 
+func Test_lisp_indent_works()
+  " This was reading beyond the end of the line
+  new
+  exe "norm a\tü(\<CR>="
+  set lisp
+  norm ==
+  bwipe!
+endfunc
+
 " vim: shiftwidth=2 sts=2 expandtab
diff --git a/src/version.c b/src/version.c
index b947061b3ff..bb3f1665fe8 100644
--- a/src/version.c
+++ b/src/version.c
@@ -732,10 +732,12 @@ static char *(features[]) =
 	NULL
 };
 
 static int included_patches[] =
 {   /* Add new patch number below this line */
+/**/
+    5151,
 /**/
     5150,
 /**/
     5149,
 /**/

Vulnerable code: 		    that++;
		    amount++;
" Tests for 'lispwords' settings being global-local
Fixed code: 		    if (*that != NUL)
		    {
			that++;
			amount++;
		    }
" Tests for 'lispwords' settings being global-local.
" And  other lisp indent stuff.
func Test_lisp_indent_works()
  " This was reading beyond the end of the line
  new
  exe "norm a\tü(\<CR>="
  set lisp
  norm ==
  bwipe!
endfunc

/**/
    5151,
CVE-2022-2206: Out-of-bounds Read (CWE-125)
value: Out-of-bounds Read in GitHub repository vim/vim prior to 8.2.
CWE description: The product reads data past the end, or before the beginning, of the intended buffer.
CVSS v3 base score: 7.8
Published: 2022-06-26T19:15Z
Repository: https://github.com/vim/vim
Language: C
Files changed: src/term.c, src/version.c
Commit date: 2022-06-25 19:54:09 +0100
Commit message: patch 8.2.5160: accessing invalid memory after changing terminal size

Problem:    Accessing invalid memory after changing terminal size.
Solution:   Adjust cmdline_row and msg_row to the value of Rows.

Diff: diff --git a/src/term.c b/src/term.c
index c1440d850f5..b365831146d 100644
--- a/src/term.c
+++ b/src/term.c
@@ -3364,10 +3364,16 @@ get_bytes_from_buf(char_u *buf, char_u *bytes, int num_bytes)
 check_shellsize(void)
 {
     if (Rows < min_rows())	// need room for one window and command line
 	Rows = min_rows();
     limit_screen_size();
+
+    // make sure these values are not invalid
+    if (cmdline_row >= Rows)
+	cmdline_row = Rows - 1;
+    if (msg_row >= Rows)
+	msg_row = Rows - 1;
 }
 
 /*
  * Limit Rows and Columns to avoid an overflow in Rows * Columns.
  */
diff --git a/src/version.c b/src/version.c
index e0a9768de18..acf84d1d2d4 100644
--- a/src/version.c
+++ b/src/version.c
@@ -733,10 +733,12 @@ static char *(features[]) =
 	NULL
 };
 
 static int included_patches[] =
 {   /* Add new patch number below this line */
+/**/
+    5160,
 /**/
     5159,
 /**/
     5158,
 /**/

Fixed code: 
    // make sure these values are not invalid
    if (cmdline_row >= Rows)
	cmdline_row = Rows - 1;
    if (msg_row >= Rows)
	msg_row = Rows - 1;
/**/
    5160,
CVE-2022-2207: Heap-based Buffer Overflow (CWE-122)
value: Heap-based Buffer Overflow in GitHub repository vim/vim prior to 8.2.
CWE description: A heap overflow condition is a buffer overflow, where the buffer that can be overwritten is allocated in the heap portion of memory, generally meaning that the buffer was allocated using a routine such as malloc().
CVSS v3 base score: 7.8
Published: 2022-06-27T12:15Z
Repository: https://github.com/vim/vim
Language: C
Files changed: src/edit.c, src/version.c
Commit date: 2022-06-26 12:59:02 +0100
Commit message: patch 8.2.5162: reading before the start of the line with BS in Replace mode

Problem:    Reading before the start of the line with BS in Replace mode.
Solution:   Check the cursor column is more than zero.

Diff: diff --git a/src/edit.c b/src/edit.c
index dbfa0ae5f99..a8e695c91c4 100644
--- a/src/edit.c
+++ b/src/edit.c
@@ -4181,11 +4181,11 @@ ins_bs(
 		ts = (int)get_sts_value();
 	    want_vcol = (want_vcol / ts) * ts;
 #endif
 
 	    // delete characters until we are at or before want_vcol
-	    while (vcol > want_vcol
+	    while (vcol > want_vcol && curwin->w_cursor.col > 0
 		    && (cc = *(ml_get_cursor() - 1), VIM_ISWHITE(cc)))
 		ins_bs_one(&vcol);
 
 	    // insert extra spaces until we are at want_vcol
 	    while (vcol < want_vcol)
diff --git a/src/version.c b/src/version.c
index 9fba35bea06..cf2e77d9fb7 100644
--- a/src/version.c
+++ b/src/version.c
@@ -733,10 +733,12 @@ static char *(features[]) =
 	NULL
 };
 
 static int included_patches[] =
 {   /* Add new patch number below this line */
+/**/
+    5162,
 /**/
     5161,
 /**/
     5160,
 /**/

Vulnerable code: 	    while (vcol > want_vcol
Fixed code: 	    while (vcol > want_vcol && curwin->w_cursor.col > 0
/**/
    5162,
CVE-2022-2208: NULL Pointer Dereference (CWE-476)
value: NULL Pointer Dereference in GitHub repository vim/vim prior to 8.2.5163.
CWE description: The product dereferences a pointer that it expects to be valid but is NULL.
CVSS v3 base score: 5.5
Published: 2022-06-27T13:15Z
Repository: https://github.com/vim/vim
Language: C
Files changed: src/diff.c, src/testdir/test_diffmode.vim, src/version.c
Commit date: 2022-06-26 14:04:07 +0100
Commit message: patch 8.2.5163: crash when deleting buffers in diff mode

Problem:    Crash when deleting buffers in diff mode.
Solution:   Recompute diffs later.  Skip window without a valid buffer.

Diff: diff --git a/src/diff.c b/src/diff.c
index df3dea0a179..eddf3316562 100644
--- a/src/diff.c
+++ b/src/diff.c
@@ -117,11 +117,16 @@ diff_buf_delete(buf_T *buf)
 	if (i != DB_COUNT)
 	{
 	    tp->tp_diffbuf[i] = NULL;
 	    tp->tp_diff_invalid = TRUE;
 	    if (tp == curtab)
-		diff_redraw(TRUE);
+	    {
+		// don't redraw right away, more might change or buffer state
+		// is invalid right now
+		need_diff_redraw = TRUE;
+		redraw_later(VALID);
+	    }
 	}
     }
 }
 
 /*
@@ -668,11 +673,12 @@ diff_redraw(
     int		used_max_fill_curwin = FALSE;
     int		n;
 
     need_diff_redraw = FALSE;
     FOR_ALL_WINDOWS(wp)
-	if (wp->w_p_diff)
+	// when closing windows or wiping buffers skip invalid window
+	if (wp->w_p_diff && buf_valid(wp->w_buffer))
 	{
 	    redraw_win_later(wp, SOME_VALID);
 	    if (wp != curwin)
 		wp_other = wp;
 #ifdef FEAT_FOLDING
diff --git a/src/testdir/test_diffmode.vim b/src/testdir/test_diffmode.vim
index 03c6c798e05..afa8f891be5 100644
--- a/src/testdir/test_diffmode.vim
+++ b/src/testdir/test_diffmode.vim
@@ -1601,7 +1601,19 @@ func Test_diff_scroll()
   call StopVimInTerminal(buf)
   call delete('Xleft')
   call delete('Xright')
 endfunc
 
+" This was trying to update diffs for a buffer being closed
+func Test_diff_only()
+  silent! lfile
+  set diff
+  lopen
+  norm o
+  silent! norm o
+
+  set nodiff
+  %bwipe!
+endfunc
+
 
 " vim: shiftwidth=2 sts=2 expandtab
diff --git a/src/version.c b/src/version.c
index cf2e77d9fb7..c847d590527 100644
--- a/src/version.c
+++ b/src/version.c
@@ -733,10 +733,12 @@ static char *(features[]) =
 	NULL
 };
 
 static int included_patches[] =
 {   /* Add new patch number below this line */
+/**/
+    5163,
 /**/
     5162,
 /**/
     5161,
 /**/

Vulnerable code: 		diff_redraw(TRUE);
	if (wp->w_p_diff)
Fixed code: 	    {
		// don't redraw right away, more might change or buffer state
		// is invalid right now
		need_diff_redraw = TRUE;
		redraw_later(VALID);
	    }
	// when closing windows or wiping buffers skip invalid window
	if (wp->w_p_diff && buf_valid(wp->w_buffer))
" This was trying to update diffs for a buffer being closed
func Test_diff_only()
  silent! lfile
  set diff
  lopen
  norm o
  silent! norm o

  set nodiff
  %bwipe!
endfunc

/**/
    5163,
CVE-2022-2210: Out-of-bounds Write (CWE-787)
value: Out-of-bounds Write in GitHub repository vim/vim prior to 8.2.
CWE description: The product writes data past the end, or before the beginning, of the intended buffer.
CVSS v3 base score: 7.8
Published: 2022-06-27T16:15Z
Repository: https://github.com/vim/vim
Language: C
Files changed: src/diff.c, src/testdir/test_diffmode.vim, src/version.c
Commit date: 2022-06-26 16:53:34 +0100
Commit message: patch 8.2.5164: invalid memory access after diff buffer manipulations

Problem:    Invalid memory access after diff buffer manipulations.
Solution:   Use zero offset when change removes all lines in a diff block.

Diff: diff --git a/src/diff.c b/src/diff.c
index eddf3316562..91e5ae2f2f6 100644
--- a/src/diff.c
+++ b/src/diff.c
@@ -401,13 +401,13 @@ diff_mark_adjust_tp(
 		check_unchanged = FALSE;
 
 		// 2. 3. 4. 5.: inserted/deleted lines touching this diff.
 		if (deleted > 0)
 		{
+		    off = 0;
 		    if (dp->df_lnum[idx] >= line1)
 		    {
-			off = dp->df_lnum[idx] - lnum_deleted;
 			if (last <= line2)
 			{
 			    // 4. delete all lines of diff
 			    if (dp->df_next != NULL
 				    && dp->df_next->df_lnum[idx] - 1 <= line2)
@@ -424,19 +424,19 @@ diff_mark_adjust_tp(
 			    dp->df_count[idx] = 0;
 			}
 			else
 			{
 			    // 5. delete lines at or just before top of diff
+			    off = dp->df_lnum[idx] - lnum_deleted;
 			    n = off;
 			    dp->df_count[idx] -= line2 - dp->df_lnum[idx] + 1;
 			    check_unchanged = TRUE;
 			}
 			dp->df_lnum[idx] = line1;
 		    }
 		    else
 		    {
-			off = 0;
 			if (last < line2)
 			{
 			    // 2. delete at end of diff
 			    dp->df_count[idx] -= last - lnum_deleted + 1;
 			    if (dp->df_next != NULL
diff --git a/src/testdir/test_diffmode.vim b/src/testdir/test_diffmode.vim
index afa8f891be5..4c7aff5ccb6 100644
--- a/src/testdir/test_diffmode.vim
+++ b/src/testdir/test_diffmode.vim
@@ -1613,7 +1613,19 @@ func Test_diff_only()
 
   set nodiff
   %bwipe!
 endfunc
 
+" This was causing invalid diff block values
+" FIXME: somehow this causes a valgrind error when run directly but not when
+" run as a test.
+func Test_diff_manipulations()
+  set diff
+  split 0
+  sil! norm RdoobdeuRdoobdeuRdoobdeu
+
+  set nodiff
+  %bwipe!
+endfunc
+
 
 " vim: shiftwidth=2 sts=2 expandtab
diff --git a/src/version.c b/src/version.c
index c847d590527..d7f0a83f3e4 100644
--- a/src/version.c
+++ b/src/version.c
@@ -733,10 +733,12 @@ static char *(features[]) =
 	NULL
 };
 
 static int included_patches[] =
 {   /* Add new patch number below this line */
+/**/
+    5164,
 /**/
     5163,
 /**/
     5162,
 /**/

Vulnerable code: 			off = dp->df_lnum[idx] - lnum_deleted;
			off = 0;
Fixed code: 		    off = 0;
			    off = dp->df_lnum[idx] - lnum_deleted;
" This was causing invalid diff block values
" FIXME: somehow this causes a valgrind error when run directly but not when
" run as a test.
func Test_diff_manipulations()
  set diff
  split 0
  sil! norm RdoobdeuRdoobdeuRdoobdeu

  set nodiff
  %bwipe!
endfunc

/**/
    5164,
CVE-2022-2257: Out-of-bounds Read (CWE-125)
value: Out-of-bounds Read in GitHub repository vim/vim prior to 9.0.
CWE description: The product reads data past the end, or before the beginning, of the intended buffer.
CVSS v3 base score: 7.8
Published: 2022-06-30T21:15Z
Repository: https://github.com/vim/vim
Language: C
Files changed: src/message.c, src/testdir/test_menu.vim, src/version.c
Commit date: 2022-06-29 21:16:58 +0100
Commit message: patch 9.0.0009: going past the end of a menu item with only modifier

Problem:    Going past the end of a menu item with only modifier.
Solution:   Check for NUL.

Diff: diff --git a/src/message.c b/src/message.c
index 02380e9177c..becb2804d00 100644
--- a/src/message.c
+++ b/src/message.c
@@ -1818,12 +1818,12 @@ str2special(
 	else
 	    // illegal byte
 	    *sp = str + 1;
     }
     else
-	// single-byte character or illegal byte
-	*sp = str + 1;
+	// single-byte character, NUL or illegal byte
+	*sp = str + (*str == NUL ? 0 : 1);
 
     // Make special keys and C0 control characters in <> form, also <M-Space>.
     // Use <Space> only for lhs of a mapping.
     if (special || c < ' ' || (from && c == ' '))
 	return get_special_key_name(c, modifiers);
diff --git a/src/testdir/test_menu.vim b/src/testdir/test_menu.vim
index c867162e5bb..df717cc8a75 100644
--- a/src/testdir/test_menu.vim
+++ b/src/testdir/test_menu.vim
@@ -526,6 +526,19 @@ func Test_tmenu()
   [TEXT]
   call assert_equal(exp, split(execute('tmenu'), "\n"))
   tunmenu Test
 endfunc
 
+func Test_only_modifier()
+  exe "tmenu a.b \x80\xfc0"
+  let exp =<< trim [TEXT]
+  --- Menus ---
+  500 a
+    500 b
+        t  - <T-2-^@>
+  [TEXT]
+  call assert_equal(exp, split(execute('tmenu'), "\n"))
+
+  tunmenu a.b
+endfunc
+
 " vim: shiftwidth=2 sts=2 expandtab
diff --git a/src/version.c b/src/version.c
index ea1cc16c715..003984ab661 100644
--- a/src/version.c
+++ b/src/version.c
@@ -733,10 +733,12 @@ static char *(features[]) =
 	NULL
 };
 
 static int included_patches[] =
 {   /* Add new patch number below this line */
+/**/
+    9,
 /**/
     8,
 /**/
     7,
 /**/

Vulnerable code: 	// single-byte character or illegal byte
	*sp = str + 1;
Fixed code: 	// single-byte character, NUL or illegal byte
	*sp = str + (*str == NUL ? 0 : 1);
func Test_only_modifier()
  exe "tmenu a.b \x80\xfc0"
  let exp =<< trim [TEXT]
  --- Menus ---
  500 a
    500 b
        t  - <T-2-^@>
  [TEXT]
  call assert_equal(exp, split(execute('tmenu'), "\n"))

  tunmenu a.b
endfunc

/**/
    9,
CVE-2022-2264: Heap-based Buffer Overflow (CWE-122)
value: Heap-based Buffer Overflow in GitHub repository vim/vim prior to 9.0.
CWE description: A heap overflow condition is a buffer overflow, where the buffer that can be overwritten is allocated in the heap portion of memory, generally meaning that the buffer was allocated using a routine such as malloc().
CVSS v3 base score: 7.8
Published: 2022-07-01T11:15Z
Repository: https://github.com/vim/vim
Language: C
Files changed: src/register.c, src/testdir/test_put.vim, src/version.c
Commit date: 2022-06-30 12:30:19 +0100
Commit message: patch 9.0.0011: reading beyond the end of the line with put command

Problem:    Reading beyond the end of the line with put command.
Solution:   Adjust the end mark position.

Diff: diff --git a/src/register.c b/src/register.c
index 93860bae624..30e2001da46 100644
--- a/src/register.c
+++ b/src/register.c
@@ -1916,10 +1916,12 @@ do_put(
 		if ((j < count - 1 || !shortline) && spaces)
 		{
 		    vim_memset(ptr, ' ', (size_t)spaces);
 		    ptr += spaces;
 		}
+		else
+		    totlen -= spaces;  // didn't use these spaces
 	    }
 
 	    // may insert some spaces after the new text
 	    vim_memset(ptr, ' ', (size_t)bd.endspaces);
 	    ptr += bd.endspaces;
diff --git a/src/testdir/test_put.vim b/src/testdir/test_put.vim
index aa5aa2b9906..66438bd3f69 100644
--- a/src/testdir/test_put.vim
+++ b/src/testdir/test_put.vim
@@ -217,7 +217,19 @@ func Test_put_empty_register()
   norm [Pi00ggv)s0
   sil! norm [P
   bwipe!
 endfunc
 
+" this was putting the end mark after the end of the line
+func Test_put_visual_mode()
+  edit! SomeNewBuffer
+  set selection=exclusive
+  exe "norm o\t"
+  m0
+  sil! norm pp
+
+  bwipe!
+  set selection&
+endfunc
+
 
 " vim: shiftwidth=2 sts=2 expandtab
diff --git a/src/version.c b/src/version.c
index c2726aa77ed..11fd817ed07 100644
--- a/src/version.c
+++ b/src/version.c
@@ -733,10 +733,12 @@ static char *(features[]) =
 	NULL
 };
 
 static int included_patches[] =
 {   /* Add new patch number below this line */
+/**/
+    11,
 /**/
     10,
 /**/
     9,
 /**/

Fixed code: 		else
		    totlen -= spaces;  // didn't use these spaces
" this was putting the end mark after the end of the line
func Test_put_visual_mode()
  edit! SomeNewBuffer
  set selection=exclusive
  exe "norm o\t"
  m0
  sil! norm pp

  bwipe!
  set selection&
endfunc

/**/
    11,
CVE-2022-2284: Heap-based Buffer Overflow (CWE-122)
value: Heap-based Buffer Overflow in GitHub repository vim/vim prior to 9.0.
CWE description: A heap overflow condition is a buffer overflow, where the buffer that can be overwritten is allocated in the heap portion of memory, generally meaning that the buffer was allocated using a routine such as malloc().
CVSS v3 base score: 7.8
Published: 2022-07-02T15:15Z
Repository: https://github.com/vim/vim
Language: C
Files changed: src/testdir/test_visual.vim, src/version.c, src/window.c
Commit date: 2022-07-01 15:26:15 +0100
Commit message: patch 9.0.0017: accessing memory beyond the end of the line

Problem:    Accessing memory beyond the end of the line.
Solution:   Stop Visual mode when closing a window.

Diff: diff --git a/src/testdir/test_visual.vim b/src/testdir/test_visual.vim
index c3230623b523..e96526654006 100644
--- a/src/testdir/test_visual.vim
+++ b/src/testdir/test_visual.vim
@@ -1467,7 +1467,19 @@ func Test_visual_paste_clipboard()
     set guioptions&
   endif
   bwipe!
 endfunc
 
+func Test_visual_area_adjusted_when_hiding()
+  " The Visual area ended after the end of the line after :hide
+  call setline(1, 'xxx')
+  vsplit Xfile
+  call setline(1, 'xxxxxxxx')
+  norm! $o
+  hid
+  norm! zW
+  bwipe!
+  bwipe!
+endfunc
+
 
 " vim: shiftwidth=2 sts=2 expandtab
diff --git a/src/version.c b/src/version.c
index 5b737e1bc68d..5d1090913517 100644
--- a/src/version.c
+++ b/src/version.c
@@ -733,10 +733,12 @@ static char *(features[]) =
 	NULL
 };
 
 static int included_patches[] =
 {   /* Add new patch number below this line */
+/**/
+    17,
 /**/
     16,
 /**/
     15,
 /**/
diff --git a/src/window.c b/src/window.c
index 992593bed982..c91ebbcfe579 100644
--- a/src/window.c
+++ b/src/window.c
@@ -2592,10 +2592,12 @@ win_close(win_T *win, int free_buf)
 	 * Be careful: If autocommands delete the window or cause this window
 	 * to be the last one left, return now.
 	 */
 	if (wp->w_buffer != curbuf)
 	{
+	    reset_VIsual_and_resel();	// stop Visual mode
+
 	    other_buffer = TRUE;
 	    win->w_closing = TRUE;
 	    apply_autocmds(EVENT_BUFLEAVE, NULL, NULL, FALSE, curbuf);
 	    if (!win_valid(win))
 		return FAIL;

Fixed code: func Test_visual_area_adjusted_when_hiding()
  " The Visual area ended after the end of the line after :hide
  call setline(1, 'xxx')
  vsplit Xfile
  call setline(1, 'xxxxxxxx')
  norm! $o
  hid
  norm! zW
  bwipe!
  bwipe!
endfunc

/**/
    17,
	    reset_VIsual_and_resel();	// stop Visual mode
CVE-2022-2285: Integer Overflow or Wraparound (CWE-190)
value: Integer Overflow or Wraparound in GitHub repository vim/vim prior to 9.0.
CWE description: The product performs a calculation that can
         produce an integer overflow or wraparound when the logic
         assumes that the resulting value will always be larger than
         the original value. This occurs when an integer value is
         incremented to a value that is too large to store in the
         associated representation. When this occurs, the value may
         become a very small or negative number.
CVSS v3 base score: 7.8
Published: 2022-07-02T16:15Z
Repository: https://github.com/vim/vim
Language: C
Files changed: src/term.c, src/testdir/test_mapping.vim, src/version.c
Commit date: 2022-07-01 16:35:45 +0100
Commit message: patch 9.0.0018: going over the end of the typahead

Problem:    Going over the end of the typahead.
Solution:   Put a NUL after the typeahead.

Diff: diff --git a/src/term.c b/src/term.c
index 754ef822d8e8..7d7b84b9a7b0 100644
--- a/src/term.c
+++ b/src/term.c
@@ -5391,10 +5391,11 @@ check_termcode(
 	 * are in Insert mode.
 	 */
 	if (*tp == ESC && !p_ek && (State & MODE_INSERT))
 	    continue;
 
+	tp[len] = NUL;
 	key_name[0] = NUL;	// no key name found yet
 	key_name[1] = NUL;	// no key name found yet
 	modifiers = 0;		// no modifiers yet
 
 #ifdef FEAT_GUI
diff --git a/src/testdir/test_mapping.vim b/src/testdir/test_mapping.vim
index ace6453f4939..2927ba718b02 100644
--- a/src/testdir/test_mapping.vim
+++ b/src/testdir/test_mapping.vim
@@ -1713,6 +1713,16 @@ func Test_map_after_timed_out_nop()
   " clean up
   call StopVimInTerminal(buf)
   call delete('Xtest_map_after_timed_out_nop')
 endfunc
 
+func Test_using_past_typeahead()
+  nnoremap :00 0
+  exe "norm :set \x80\xfb0=0\<CR>"
+  exe "sil norm :0\x0f\<C-U>\<CR>"
+
+  exe "norm :set \x80\xfb0=\<CR>"
+  nunmap :00
+endfunc
+
+
 " vim: shiftwidth=2 sts=2 expandtab
diff --git a/src/version.c b/src/version.c
index 5d1090913517..6415b59caf32 100644
--- a/src/version.c
+++ b/src/version.c
@@ -733,10 +733,12 @@ static char *(features[]) =
 	NULL
 };
 
 static int included_patches[] =
 {   /* Add new patch number below this line */
+/**/
+    18,
 /**/
     17,
 /**/
     16,
 /**/

Fixed code: 	tp[len] = NUL;
func Test_using_past_typeahead()
  nnoremap :00 0
  exe "norm :set \x80\xfb0=0\<CR>"
  exe "sil norm :0\x0f\<C-U>\<CR>"

  exe "norm :set \x80\xfb0=\<CR>"
  nunmap :00
endfunc


/**/
    18,
CVE-2022-2286: Out-of-bounds Read (CWE-125)
value: Out-of-bounds Read in GitHub repository vim/vim prior to 9.0.
CWE description: The product reads data past the end, or before the beginning, of the intended buffer.
CVSS v3 base score: 7.8
Published: 2022-07-02T19:15Z
Repository: https://github.com/vim/vim
Language: C
Files changed: src/insexpand.c, src/testdir/test_ins_complete.vim, src/version.c
Commit date: 2022-07-01 19:58:30 +0100
Commit message: patch 9.0.0020: with some completion reading past end of string

Problem:    With some completion reading past end of string.
Solution:   Check the length of the string.

Diff: diff --git a/src/insexpand.c b/src/insexpand.c
index 4a5feac9dc1f..734550ffd231 100644
--- a/src/insexpand.c
+++ b/src/insexpand.c
@@ -2207,15 +2207,25 @@ ins_compl_stop(int c, int prev_mode, int retval)
 
     // CTRL-E means completion is Ended, go back to the typed text.
     // but only do this, if the Popup is still visible
     if (c == Ctrl_E)
     {
+	char_u *p = NULL;
+
 	ins_compl_delete();
 	if (compl_leader != NULL)
-	    ins_bytes(compl_leader + get_compl_len());
+	    p = compl_leader;
 	else if (compl_first_match != NULL)
-	    ins_bytes(compl_orig_text + get_compl_len());
+	    p = compl_orig_text;
+	if (p != NULL)
+	{
+	    int	    compl_len = get_compl_len();
+	    int	    len = (int)STRLEN(p);
+
+	    if (len > compl_len)
+		ins_bytes_len(p + compl_len, len - compl_len);
+	}
 	retval = TRUE;
     }
 
     auto_format(FALSE, TRUE);
 
diff --git a/src/testdir/test_ins_complete.vim b/src/testdir/test_ins_complete.vim
index 365c646a19c6..20c2b4f48f41 100644
--- a/src/testdir/test_ins_complete.vim
+++ b/src/testdir/test_ins_complete.vim
@@ -2182,6 +2182,14 @@ func Test_complete_smartindent()
   call assert_equal(['', '{','}',''], result)
   bw!
   delfunction! FooBarComplete
 endfunc
 
+func Test_complete_overrun()
+  " this was going past the end of the copied text
+  new
+  sil norm si0s0
+  bwipe!
+endfunc
+
+
 " vim: shiftwidth=2 sts=2 expandtab
diff --git a/src/version.c b/src/version.c
index 42e9135e1f6d..26cb768a8254 100644
--- a/src/version.c
+++ b/src/version.c
@@ -733,10 +733,12 @@ static char *(features[]) =
 	NULL
 };
 
 static int included_patches[] =
 {   /* Add new patch number below this line */
+/**/
+    20,
 /**/
     19,
 /**/
     18,
 /**/

Vulnerable code: 	    ins_bytes(compl_leader + get_compl_len());
	    ins_bytes(compl_orig_text + get_compl_len());
Fixed code: 	char_u *p = NULL;

	    p = compl_leader;
	    p = compl_orig_text;
	if (p != NULL)
	{
	    int	    compl_len = get_compl_len();
	    int	    len = (int)STRLEN(p);

	    if (len > compl_len)
		ins_bytes_len(p + compl_len, len - compl_len);
	}
func Test_complete_overrun()
  " this was going past the end of the copied text
  new
  sil norm si0s0
  bwipe!
endfunc


/**/
    20,
CVE-2022-2288: Out-of-bounds Write (CWE-787)
value: Out-of-bounds Write in GitHub repository vim/vim prior to 9.0.
CWE description: The product writes data past the end, or before the beginning, of the intended buffer.
CVSS v3 base score: 7.8
Published: 2022-07-03T13:15Z
Repository: https://github.com/vim/vim
Language: C
Files changed: src/ex_docmd.c, src/testdir/test_cmdline.vim, src/version.c
Commit date: 2022-07-02 13:43:21 +0100
Commit message: patch 9.0.0025: accessing beyond allocated memory with the cmdline window

Problem:    Accessing beyond allocated memory when using the cmdline window in
            Ex mode.
Solution:   Use "*" instead of "'<,'>" for Visual mode.

Diff: diff --git a/src/ex_docmd.c b/src/ex_docmd.c
index 271e7e246635..697337cad957 100644
--- a/src/ex_docmd.c
+++ b/src/ex_docmd.c
@@ -3116,13 +3116,15 @@ parse_command_modifiers(
 	    if (use_plus_cmd)
 	    {
 		size_t len = STRLEN(cmd_start);
 
 		// Special case: empty command uses "+":
-		//  "'<,'>mods" -> "mods'<,'>+
+		//  "'<,'>mods" -> "mods *+
+		//  Use "*" instead of "'<,'>" to avoid the command getting
+		//  longer, in case is was allocated.
 		mch_memmove(orig_cmd, cmd_start, len);
-		STRCPY(orig_cmd + len, "'<,'>+");
+		STRCPY(orig_cmd + len, " *+");
 	    }
 	    else
 	    {
 		mch_memmove(cmd_start - 5, cmd_start, eap->cmd - cmd_start);
 		eap->cmd -= 5;
diff --git a/src/testdir/test_cmdline.vim b/src/testdir/test_cmdline.vim
index 36853369855e..f0498a146626 100644
--- a/src/testdir/test_cmdline.vim
+++ b/src/testdir/test_cmdline.vim
@@ -2101,10 +2101,18 @@ func Test_cmdwin_insert_mode_close()
   exe "normal q:a\<C-C>let s='Hello'\<CR>"
   call assert_equal('Hello', s)
   call assert_equal(1, winnr('$'))
 endfunc
 
+func Test_cmdwin_ex_mode_with_modifier()
+  " this was accessing memory after allocated text in Ex mode
+  new
+  call setline(1, ['some', 'text', 'lines'])
+  silent! call feedkeys("gQnormal vq:atopleft\<C-V>\<CR>\<CR>", 'xt')
+  bwipe!
+endfunc
+
 " test that ";" works to find a match at the start of the first line
 func Test_zero_line_search()
   new
   call setline(1, ["1, pattern", "2, ", "3, pattern"])
   call cursor(1,1)
diff --git a/src/version.c b/src/version.c
index e8d506c905a0..8c9325d9410e 100644
--- a/src/version.c
+++ b/src/version.c
@@ -733,10 +733,12 @@ static char *(features[]) =
 	NULL
 };
 
 static int included_patches[] =
 {   /* Add new patch number below this line */
+/**/
+    25,
 /**/
     24,
 /**/
     23,
 /**/

Vulnerable code: 		//  "'<,'>mods" -> "mods'<,'>+
		STRCPY(orig_cmd + len, "'<,'>+");
Fixed code: 		//  "'<,'>mods" -> "mods *+
		//  Use "*" instead of "'<,'>" to avoid the command getting
		//  longer, in case is was allocated.
		STRCPY(orig_cmd + len, " *+");
func Test_cmdwin_ex_mode_with_modifier()
  " this was accessing memory after allocated text in Ex mode
  new
  call setline(1, ['some', 'text', 'lines'])
  silent! call feedkeys("gQnormal vq:atopleft\<C-V>\<CR>\<CR>", 'xt')
  bwipe!
endfunc

/**/
    25,
CVE-2022-2344: Heap-based Buffer Overflow (CWE-122)
value: Heap-based Buffer Overflow in GitHub repository vim/vim prior to 9.0.0045.
CWE description: A heap overflow condition is a buffer overflow, where the buffer that can be overwritten is allocated in the heap portion of memory, generally meaning that the buffer was allocated using a routine such as malloc().
CVSS v3 base score: 7.8
Published: 2022-07-08T19:15Z
Repository: https://github.com/vim/vim
Language: C
Files changed: src/insexpand.c, src/testdir/test_ins_complete.vim, src/version.c
Commit date: 2022-07-07 19:59:49 +0100
Commit message: patch 9.0.0046: reading past end of completion with duplicate match

Problem:    Reading past end of completion with duplicate match.
Solution:   Check string length

Diff: diff --git a/src/insexpand.c b/src/insexpand.c
index 0ecb6560c5fc..9c598a89f73d 100644
--- a/src/insexpand.c
+++ b/src/insexpand.c
@@ -784,11 +784,12 @@ ins_compl_add(
 	match = compl_first_match;
 	do
 	{
 	    if (!match_at_original_text(match)
 		    && STRNCMP(match->cp_str, str, len) == 0
-		    && match->cp_str[len] == NUL)
+		    && ((int)STRLEN(match->cp_str) <= len
+						 || match->cp_str[len] == NUL))
 		return NOTDONE;
 	    match = match->cp_next;
 	} while (match != NULL && !is_first_match(match));
     }
 
diff --git a/src/testdir/test_ins_complete.vim b/src/testdir/test_ins_complete.vim
index 5e5b1bbece68..2be6d0602037 100644
--- a/src/testdir/test_ins_complete.vim
+++ b/src/testdir/test_ins_complete.vim
@@ -2110,7 +2110,17 @@ func Test_infercase_very_long_line()
 
   bwipe!
   set noic noinfercase
 endfunc
 
+func Test_ins_complete_add()
+  " this was reading past the end of allocated memory
+  new
+  norm o
+  norm 7o
+  sil! norm o
+
+  bwipe!
+endfunc
+
 
 " vim: shiftwidth=2 sts=2 expandtab
diff --git a/src/version.c b/src/version.c
index 75de2fc7b751..de8e968f42f8 100644
--- a/src/version.c
+++ b/src/version.c
@@ -733,10 +733,12 @@ static char *(features[]) =
 	NULL
 };
 
 static int included_patches[] =
 {   /* Add new patch number below this line */
+/**/
+    46,
 /**/
     45,
 /**/
     44,
 /**/

Vulnerable code: 		    && match->cp_str[len] == NUL)
Fixed code: 		    && ((int)STRLEN(match->cp_str) <= len
						 || match->cp_str[len] == NUL))
func Test_ins_complete_add()
  " this was reading past the end of allocated memory
  new
  norm o
  norm 7o
  sil! norm o

  bwipe!
endfunc

/**/
    46,
CVE-2022-2522: Heap-based Buffer Overflow (CWE-122)
value: Heap-based Buffer Overflow in GitHub repository vim/vim prior to 9.0.0061.
CWE description: A heap overflow condition is a buffer overflow, where the buffer that can be overwritten is allocated in the heap portion of memory, generally meaning that the buffer was allocated using a routine such as malloc().
CVSS v3 base score: 7.8
Published: 2022-07-25T14:15Z
Repository: https://github.com/vim/vim
Language: C
Files changed: src/insexpand.c, src/testdir/test_ins_complete.vim, src/version.c
Commit date: 2022-07-23 06:53:08 +0100
Commit message: patch 9.0.0060: accessing uninitialized memory when completing long line

Problem:    Accessing uninitialized memory when completing long line.
Solution:   Terminate string with NUL.

Diff: diff --git a/src/insexpand.c b/src/insexpand.c
index b49a631a6b4f..c505158a1db2 100644
--- a/src/insexpand.c
+++ b/src/insexpand.c
@@ -640,10 +640,11 @@ ins_compl_infercase_gettext(
 	    // ASCII characters, and we also need one byte for NUL, so when
 	    // getting to six bytes from the edge of IObuff switch to using a
 	    // growarray.  Add the character in the next round.
 	    if (ga_grow(&gap, IOSIZE) == FAIL)
 		return (char_u *)"[failed]";
+	    *p = NUL;
 	    STRCPY(gap.ga_data, IObuff);
 	    gap.ga_len = (int)STRLEN(IObuff);
 	}
 	else if (has_mbyte)
 	    p += (*mb_char2bytes)(wca[i++], p);
diff --git a/src/testdir/test_ins_complete.vim b/src/testdir/test_ins_complete.vim
index 2be6d0602037..7bebc5d8a996 100644
--- a/src/testdir/test_ins_complete.vim
+++ b/src/testdir/test_ins_complete.vim
@@ -2106,10 +2106,17 @@ func Test_infercase_very_long_line()
   call setline(2, longLine)
   set ic infercase
   exe "normal 2Go\<C-X>\<C-L>\<Esc>"
   call assert_equal(longLine, getline(3))
 
+  " check that the too long text is NUL terminated
+  %del
+  norm o
+  norm 1987ax
+  exec "norm ox\<C-X>\<C-L>"
+  call assert_equal(repeat('x', 1987), getline(3))
+
   bwipe!
   set noic noinfercase
 endfunc
 
 func Test_ins_complete_add()
diff --git a/src/version.c b/src/version.c
index b57ab6985f51..b6e61f50ef16 100644
--- a/src/version.c
+++ b/src/version.c
@@ -733,10 +733,12 @@ static char *(features[]) =
 	NULL
 };
 
 static int included_patches[] =
 {   /* Add new patch number below this line */
+/**/
+    60,
 /**/
     59,
 /**/
     58,
 /**/

Fixed code: 	    *p = NUL;
  " check that the too long text is NUL terminated
  %del
  norm o
  norm 1987ax
  exec "norm ox\<C-X>\<C-L>"
  call assert_equal(repeat('x', 1987), getline(3))

/**/
    60,
CVE-2022-2571: Heap-based Buffer Overflow (CWE-122)
value: Heap-based Buffer Overflow in GitHub repository vim/vim prior to 9.0.0101.
CWE description: A heap overflow condition is a buffer overflow, where the buffer that can be overwritten is allocated in the heap portion of memory, generally meaning that the buffer was allocated using a routine such as malloc().
CVSS v3 base score: 7.8
Published: 2022-08-01T15:15Z
Repository: https://github.com/vim/vim
Language: C
Files changed: src/insexpand.c, src/testdir/test_ins_complete.vim, src/version.c
Commit date: 2022-07-28 21:51:37 +0100
Commit message: patch 9.0.0102: reading past end of line with insert mode completion

Problem:    Reading past end of line with insert mode completion.
Solution:   Check text length.

Diff: diff --git a/src/insexpand.c b/src/insexpand.c
index 7339ce9c6e3a..fc3eff071341 100644
--- a/src/insexpand.c
+++ b/src/insexpand.c
@@ -3499,11 +3499,11 @@ ins_comp_get_next_word_or_line(
     }
     else
     {
 	char_u	*tmp_ptr = ptr;
 
-	if (compl_status_adding())
+	if (compl_status_adding() && compl_length <= (int)STRLEN(tmp_ptr))
 	{
 	    tmp_ptr += compl_length;
 	    // Skip if already inside a word.
 	    if (vim_iswordp(tmp_ptr))
 		return NULL;
diff --git a/src/testdir/test_ins_complete.vim b/src/testdir/test_ins_complete.vim
index 35c5785d3a09..2b0a2947a0e8 100644
--- a/src/testdir/test_ins_complete.vim
+++ b/src/testdir/test_ins_complete.vim
@@ -2140,7 +2140,15 @@ func Test_ins_complete_add()
   sil! norm o
 
   bwipe!
 endfunc
 
+func Test_ins_complete_end_of_line()
+  " this was reading past the end of the line
+  new  
+  norm 8oý 
+  sil! norm o
+
+  bwipe!
+endfunc
 
 " vim: shiftwidth=2 sts=2 expandtab
diff --git a/src/version.c b/src/version.c
index 1241e98b08b0..ce6caa5092ef 100644
--- a/src/version.c
+++ b/src/version.c
@@ -733,10 +733,12 @@ static char *(features[]) =
 	NULL
 };
 
 static int included_patches[] =
 {   /* Add new patch number below this line */
+/**/
+    102,
 /**/
     101,
 /**/
     100,
 /**/

Vulnerable code: 	if (compl_status_adding())
Fixed code: 	if (compl_status_adding() && compl_length <= (int)STRLEN(tmp_ptr))
func Test_ins_complete_end_of_line()
  " this was reading past the end of the line
  new  
  norm 8oý 
  sil! norm o

  bwipe!
endfunc
/**/
    102,
CVE-2022-2580: Heap-based Buffer Overflow (CWE-122)
value: Heap-based Buffer Overflow in GitHub repository vim/vim prior to 9.0.0102.
CWE description: A heap overflow condition is a buffer overflow, where the buffer that can be overwritten is allocated in the heap portion of memory, generally meaning that the buffer was allocated using a routine such as malloc().
CVSS v3 base score: 7.8
Published: 2022-08-01T15:15Z
Repository: https://github.com/vim/vim
Language: C
Files changed: src/testdir/test_eval_stuff.vim, src/typval.c, src/version.c
Commit date: 2022-07-29 15:28:27 +0100
Commit message: patch 9.0.0104: going beyond allocated memory when evaluating string constant

Problem:    Going beyond allocated memory when evaluating string constant.
Solution:   Properly skip over <Key> form.

Diff: diff --git a/src/testdir/test_eval_stuff.vim b/src/testdir/test_eval_stuff.vim
index 3c168f2f59b5..c63082e8e8b6 100644
--- a/src/testdir/test_eval_stuff.vim
+++ b/src/testdir/test_eval_stuff.vim
@@ -615,6 +615,11 @@ func Test_modified_char_no_escape_special()
   nunmap <F2>
   unlet g:got_m_ellipsis
   nunmap <M-…>
 endfunc
 
+func Test_eval_string_in_special_key()
+  " this was using the '{' inside <> as the start of an interpolated string
+  silent! echo 0{1-$"\<S--{>n|nö%
+endfunc
+
 " vim: shiftwidth=2 sts=2 expandtab
diff --git a/src/typval.c b/src/typval.c
index a266330622c8..8b69adfcc8b8 100644
--- a/src/typval.c
+++ b/src/typval.c
@@ -2088,11 +2088,23 @@ eval_string(char_u **arg, typval_T *rettv, int evaluate, int interpolate)
 	    ++p;
 	    // A "\<x>" form occupies at least 4 characters, and produces up
 	    // to 9 characters (6 for the char and 3 for a modifier):
 	    // reserve space for 5 extra.
 	    if (*p == '<')
+	    {
+		int		modifiers = 0;
+		int		flags = FSK_KEYCODE | FSK_IN_STRING;
+
 		extra += 5;
+
+		// Skip to the '>' to avoid using '{' inside for string
+		// interpolation.
+		if (p[1] != '*')
+		    flags |= FSK_SIMPLIFY;
+		if (find_special_key(&p, &modifiers, flags, NULL) != 0)
+		    --p;  // leave "p" on the ">"
+	    }
 	}
 	else if (interpolate && (*p == '{' || *p == '}'))
 	{
 	    if (*p == '{' && p[1] != '{') // start of expression
 		break;
diff --git a/src/version.c b/src/version.c
index 9f6b19499ea0..8c55a62e9d2c 100644
--- a/src/version.c
+++ b/src/version.c
@@ -733,10 +733,12 @@ static char *(features[]) =
 	NULL
 };
 
 static int included_patches[] =
 {   /* Add new patch number below this line */
+/**/
+    104,
 /**/
     103,
 /**/
     102,
 /**/

Fixed code: func Test_eval_string_in_special_key()
  " this was using the '{' inside <> as the start of an interpolated string
  silent! echo 0{1-$"\<S--{>n|nö%
endfunc

	    {
		int		modifiers = 0;
		int		flags = FSK_KEYCODE | FSK_IN_STRING;


		// Skip to the '>' to avoid using '{' inside for string
		// interpolation.
		if (p[1] != '*')
		    flags |= FSK_SIMPLIFY;
		if (find_special_key(&p, &modifiers, flags, NULL) != 0)
		    --p;  // leave "p" on the ">"
	    }
/**/
    104,