CVE-2022-3235: Use After Free (CWE-416)
value: Use After Free in GitHub repository vim/vim prior to 9.0.0490.
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-18T20:15Z
Repository: https://github.com/vim/vim
Language: C
Files changed: src/ex_getln.c, src/testdir/test_cmdwin.vim, src/version.c
Commit date: 2022-09-17 19:43:23 +0100
Commit message: patch 9.0.0490: using freed memory with cmdwin and BufEnter autocmd

Problem:    Using freed memory with cmdwin and BufEnter autocmd.
Solution:   Make sure pointer to b_p_iminsert is still valid.

Diff: diff --git a/src/ex_getln.c b/src/ex_getln.c
index 70436b31f05e..a4fb61145c96 100644
--- a/src/ex_getln.c
+++ b/src/ex_getln.c
@@ -1585,10 +1585,11 @@ getcmdline_int(
 #ifdef FEAT_EVAL
     int		break_ctrl_c = FALSE;
 #endif
     expand_T	xpc;
     long	*b_im_ptr = NULL;
+    buf_T	*b_im_ptr_buf = NULL;	// buffer where b_im_ptr is valid
     cmdline_info_T save_ccline;
     int		did_save_ccline = FALSE;
     int		cmdline_type;
     int		wild_type;
 
@@ -1681,10 +1682,11 @@ getcmdline_int(
 	// Use ":lmap" mappings for search pattern and input().
 	if (curbuf->b_p_imsearch == B_IMODE_USE_INSERT)
 	    b_im_ptr = &curbuf->b_p_iminsert;
 	else
 	    b_im_ptr = &curbuf->b_p_imsearch;
+	b_im_ptr_buf = curbuf;
 	if (*b_im_ptr == B_IMODE_LMAP)
 	    State |= MODE_LANGMAP;
 #ifdef HAVE_INPUT_METHOD
 	im_set_active(*b_im_ptr == B_IMODE_IM);
 #endif
@@ -2032,11 +2034,12 @@ getcmdline_int(
 		ui_cursor_shape();	// may show different cursor shape
 #endif
 		goto cmdline_not_changed;
 
 	case Ctrl_HAT:
-		cmdline_toggle_langmap(b_im_ptr);
+		cmdline_toggle_langmap(
+				    buf_valid(b_im_ptr_buf) ? b_im_ptr : NULL);
 		goto cmdline_not_changed;
 
 //	case '@':   only in very old vi
 	case Ctrl_U:
 		// delete all characters left of the cursor
@@ -2542,11 +2545,12 @@ returncmd:
     if (!debug_mode)
 	may_trigger_modechanged();
 #endif
 
 #ifdef HAVE_INPUT_METHOD
-    if (b_im_ptr != NULL && *b_im_ptr != B_IMODE_LMAP)
+    if (b_im_ptr != NULL && buf_valid(b_im_ptr_buf)
+						  && *b_im_ptr != B_IMODE_LMAP)
 	im_save_status(b_im_ptr);
     im_set_active(FALSE);
 #endif
     setmouse();
 #ifdef CURSOR_SHAPE
diff --git a/src/testdir/test_cmdwin.vim b/src/testdir/test_cmdwin.vim
index d62673aba254..fe849bcc1686 100644
--- a/src/testdir/test_cmdwin.vim
+++ b/src/testdir/test_cmdwin.vim
@@ -376,7 +376,17 @@ endfunc
 func Test_normal_escape()
   call feedkeys("q:i\" foo\<Esc>:normal! \<C-V>\<Esc>\<CR>:\" bar\<CR>", 'ntx')
   call assert_equal('" bar', @:)
 endfunc
 
+" This was using a pointer to a freed buffer
+func Test_cmdwin_freed_buffer_ptr()
+  au BufEnter * next 0| file 
+  edit 0
+  silent! norm q/
+
+  au! BufEnter
+  bwipe!
+endfunc
+
 
 " vim: shiftwidth=2 sts=2 expandtab
diff --git a/src/version.c b/src/version.c
index f4c5fb4a8938..7d7ac1654e77 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 */
+/**/
+    490,
 /**/
     489,
 /**/
     488,
 /**/

Vulnerable code: 		cmdline_toggle_langmap(b_im_ptr);
    if (b_im_ptr != NULL && *b_im_ptr != B_IMODE_LMAP)
Fixed code:     buf_T	*b_im_ptr_buf = NULL;	// buffer where b_im_ptr is valid
	b_im_ptr_buf = curbuf;
		cmdline_toggle_langmap(
				    buf_valid(b_im_ptr_buf) ? b_im_ptr : NULL);
    if (b_im_ptr != NULL && buf_valid(b_im_ptr_buf)
						  && *b_im_ptr != B_IMODE_LMAP)
" This was using a pointer to a freed buffer
func Test_cmdwin_freed_buffer_ptr()
  au BufEnter * next 0| file 
  edit 0
  silent! norm q/

  au! BufEnter
  bwipe!
endfunc

/**/
    490,