CVE-2022-3099: Use After Free (CWE-416)
value: Use After Free in GitHub repository vim/vim prior to 9.0.0360.
CWE description: The product reuses or references memory after it has been freed. At some point afterward, the memory may be allocated again and saved in another pointer, while the original pointer references a location somewhere within the new allocation. Any operations using the original pointer are no longer valid because the memory "belongs" to the code that operates on the new pointer.
CVSS v3 base score: 7.8
Published: 2022-09-03T16:15Z
Repository: https://github.com/vim/vim
Language: C
Files changed: src/ex_docmd.c, src/testdir/test_eval_stuff.vim, src/version.c
Commit date: 2022-09-02 16:47:16 +0100
Commit message: patch 9.0.0360: crash when invalid line number on :for is ignored

Problem:    Crash when invalid line number on :for is ignored.
Solution:   Do not check breakpoint for non-existing line.

Diff: diff --git a/src/ex_docmd.c b/src/ex_docmd.c
index ae1f1959b715..0b6b21712111 100644
--- a/src/ex_docmd.c
+++ b/src/ex_docmd.c
@@ -1066,11 +1066,11 @@ do_cmdline(
 		    cstack.cs_lflags |= CSL_HAD_LOOP;
 		    line_breakcheck();		// check if CTRL-C typed
 
 		    // Check for the next breakpoint at or after the ":while"
 		    // or ":for".
-		    if (breakpoint != NULL)
+		    if (breakpoint != NULL && lines_ga.ga_len > current_line)
 		    {
 			*breakpoint = dbg_find_breakpoint(
 			       getline_equal(fgetline, cookie, getsourceline),
 									fname,
 			   ((wcmd_T *)lines_ga.ga_data)[current_line].lnum-1);
diff --git a/src/testdir/test_eval_stuff.vim b/src/testdir/test_eval_stuff.vim
index 313d791850c0..934286bbe841 100644
--- a/src/testdir/test_eval_stuff.vim
+++ b/src/testdir/test_eval_stuff.vim
@@ -1,8 +1,9 @@
 " Tests for various eval things.
 
 source view_util.vim
+source shared.vim
 
 function s:foo() abort
   try
     return [] == 0
   catch
@@ -85,10 +86,22 @@ func Test_for_over_null_string()
   call assert_equal(0, cnt)
 
   let &enc = save_enc
 endfunc
 
+func Test_for_invalid_line_count()
+  let lines =<< trim END
+      111111111111111111111111 for line in ['one']
+      endfor
+  END
+  call writefile(lines, 'XinvalidFor')
+  " only test that this doesn't crash
+  call RunVim([], [], '-u NONE -e -s -S XinvalidFor -c qa')
+
+  call delete('XinvalidFor')
+endfunc
+
 func Test_readfile_binary()
   new
   call setline(1, ['one', 'two', 'three'])
   setlocal ff=dos
   silent write XReadfile_bin
diff --git a/src/version.c b/src/version.c
index fa2d9d54e258..4f2b3dcf15a4 100644
--- a/src/version.c
+++ b/src/version.c
@@ -705,10 +705,12 @@ static char *(features[]) =
 	NULL
 };
 
 static int included_patches[] =
 {   /* Add new patch number below this line */
+/**/
+    360,
 /**/
     359,
 /**/
     358,
 /**/

Vulnerable code: 		    if (breakpoint != NULL)
Fixed code: 		    if (breakpoint != NULL && lines_ga.ga_len > current_line)
source shared.vim
func Test_for_invalid_line_count()
  let lines =<< trim END
      111111111111111111111111 for line in ['one']
      endfor
  END
  call writefile(lines, 'XinvalidFor')
  " only test that this doesn't crash
  call RunVim([], [], '-u NONE -e -s -S XinvalidFor -c qa')

  call delete('XinvalidFor')
endfunc

/**/
    360,