CVE-2022-3134: Use After Free (CWE-416)
value: Use After Free in GitHub repository vim/vim prior to 9.0.0389.
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-06T20:15Z
Repository: https://github.com/vim/vim
Language: C
Files changed: src/errors.h, src/tag.c, src/testdir/test_tagfunc.vim, src/version.c
Commit date: 2022-09-05 19:51:13 +0100
Commit message: patch 9.0.0389: crash when 'tagfunc' closes the window

Problem:    Crash when 'tagfunc' closes the window.
Solution:   Bail out when the window was closed.

Diff: diff --git a/src/errors.h b/src/errors.h
index ee75d07e5c9e..44eb9db9fcf5 100644
--- a/src/errors.h
+++ b/src/errors.h
@@ -3322,5 +3322,7 @@ EXTERN char e_can_only_use_left_padding_when_column_is_zero[]
 EXTERN char e_non_null_dict_required_for_argument_nr[]
 	INIT(= N_("E1297: Non-NULL Dictionary required for argument %d"));
 EXTERN char e_non_null_list_required_for_argument_nr[]
 	INIT(= N_("E1298: Non-NULL List required for argument %d"));
 #endif
+EXTERN char e_window_unexpectedly_close_while_searching_for_tags[]
+	INIT(= N_("E1299: Window unexpectedly closed while searching for tags"));
diff --git a/src/tag.c b/src/tag.c
index c3e23f624ef2..d07fbbe99c29 100644
--- a/src/tag.c
+++ b/src/tag.c
@@ -688,10 +688,20 @@ do_tag(
 					    max_num_matches, buf_ffname) == OK
 		    && new_num_matches < max_num_matches)
 		max_num_matches = MAXCOL; // If less than max_num_matches
 					  // found: all matches found.
 
+	    // A tag function may do anything, which may cause various
+	    // information to become invalid.  At least check for the tagstack
+	    // to still be the same.
+	    if (tagstack != curwin->w_tagstack)
+	    {
+		emsg(_(e_window_unexpectedly_close_while_searching_for_tags));
+		FreeWild(new_num_matches, new_matches);
+		break;
+	    }
+
 	    // If there already were some matches for the same name, move them
 	    // to the start.  Avoids that the order changes when using
 	    // ":tnext" and jumping to another file.
 	    if (!new_tag && !other_name)
 	    {
diff --git a/src/testdir/test_tagfunc.vim b/src/testdir/test_tagfunc.vim
index 95826121cd84..5b18976903f6 100644
--- a/src/testdir/test_tagfunc.vim
+++ b/src/testdir/test_tagfunc.vim
@@ -399,6 +399,19 @@ func Test_tagfunc_wipes_buffer()
 
   delfunc g:Tag0unc0
   set tagfunc=
 endfunc
 
+func Test_tagfunc_closes_window()
+  split any
+  func MytagfuncClose(pat, flags, info)
+    close
+    return [{'name' : 'mytag', 'filename' : 'Xtest', 'cmd' : '1'}]
+  endfunc
+  set tagfunc=MytagfuncClose
+  call assert_fails('tag xyz', 'E1299:')
+
+  set tagfunc=
+endfunc
+
+
 " vim: shiftwidth=2 sts=2 expandtab
diff --git a/src/version.c b/src/version.c
index d4fc4d585f99..b114c2760d84 100644
--- a/src/version.c
+++ b/src/version.c
@@ -701,10 +701,12 @@ static char *(features[]) =
 	NULL
 };
 
 static int included_patches[] =
 {   /* Add new patch number below this line */
+/**/
+    389,
 /**/
     388,
 /**/
     387,
 /**/

Fixed code: EXTERN char e_window_unexpectedly_close_while_searching_for_tags[]
	INIT(= N_("E1299: Window unexpectedly closed while searching for tags"));
	    // A tag function may do anything, which may cause various
	    // information to become invalid.  At least check for the tagstack
	    // to still be the same.
	    if (tagstack != curwin->w_tagstack)
	    {
		emsg(_(e_window_unexpectedly_close_while_searching_for_tags));
		FreeWild(new_num_matches, new_matches);
		break;
	    }

func Test_tagfunc_closes_window()
  split any
  func MytagfuncClose(pat, flags, info)
    close
    return [{'name' : 'mytag', 'filename' : 'Xtest', 'cmd' : '1'}]
  endfunc
  set tagfunc=MytagfuncClose
  call assert_fails('tag xyz', 'E1299:')

  set tagfunc=
endfunc


/**/
    389,