CVE-2022-3256: Use After Free (CWE-416)
value: Use After Free in GitHub repository vim/vim prior to 9.0.0530.
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-22T13:15Z
Repository: https://github.com/vim/vim
Language: C
Files changed: src/mark.c, src/testdir/test_marks.vim, src/version.c
Commit date: 2022-09-21 13:07:22 +0100
Commit message: patch 9.0.0530: using freed memory when autocmd changes mark

Problem:    Using freed memory when autocmd changes mark.
Solution:   Copy the mark before editing another buffer.

Diff: diff --git a/src/mark.c b/src/mark.c
index ade5a1087b7d..584db033d3ca 100644
--- a/src/mark.c
+++ b/src/mark.c
@@ -219,21 +219,23 @@ movemark(int count)
 	jmp = curwin->w_jumplist + curwin->w_jumplistidx;
 	if (jmp->fmark.fnum == 0)
 	    fname2fnum(jmp);
 	if (jmp->fmark.fnum != curbuf->b_fnum)
 	{
-	    // jump to other file
-	    if (buflist_findnr(jmp->fmark.fnum) == NULL)
+	    // Make a copy, an autocommand may make "jmp" invalid.
+	    fmark_T fmark = jmp->fmark;
+
+	    // jump to the file with the mark
+	    if (buflist_findnr(fmark.fnum) == NULL)
 	    {					     // Skip this one ..
 		count += count < 0 ? -1 : 1;
 		continue;
 	    }
-	    if (buflist_getfile(jmp->fmark.fnum, jmp->fmark.mark.lnum,
-							    0, FALSE) == FAIL)
+	    if (buflist_getfile(fmark.fnum, fmark.mark.lnum, 0, FALSE) == FAIL)
 		return (pos_T *)NULL;
 	    // Set lnum again, autocommands my have changed it
-	    curwin->w_cursor = jmp->fmark.mark;
+	    curwin->w_cursor = fmark.mark;
 	    pos = (pos_T *)-1;
 	}
 	else
 	    pos = &(jmp->fmark.mark);
 	return pos;
diff --git a/src/testdir/test_marks.vim b/src/testdir/test_marks.vim
index 12501a3aba07..20fb3041f244 100644
--- a/src/testdir/test_marks.vim
+++ b/src/testdir/test_marks.vim
@@ -303,6 +303,19 @@ func Test_getmarklist()
         \ bufnr()->getmarklist()[0])
   call assert_equal([], {}->getmarklist())
   close!
 endfunc
 
+" This was using freed memory
+func Test_jump_mark_autocmd()
+  next 00
+  edit 0
+  sargument
+  au BufEnter 0 all
+  sil norm 
+
+  au! BufEnter
+  bwipe!
+endfunc
+
+
 " vim: shiftwidth=2 sts=2 expandtab
diff --git a/src/version.c b/src/version.c
index 555adf57e03f..cefa82a3372e 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 */
+/**/
+    530,
 /**/
     529,
 /**/
     528,
 /**/

Vulnerable code: 	    // jump to other file
	    if (buflist_findnr(jmp->fmark.fnum) == NULL)
	    if (buflist_getfile(jmp->fmark.fnum, jmp->fmark.mark.lnum,
							    0, FALSE) == FAIL)
	    curwin->w_cursor = jmp->fmark.mark;
Fixed code: 	    // Make a copy, an autocommand may make "jmp" invalid.
	    fmark_T fmark = jmp->fmark;

	    // jump to the file with the mark
	    if (buflist_findnr(fmark.fnum) == NULL)
	    if (buflist_getfile(fmark.fnum, fmark.mark.lnum, 0, FALSE) == FAIL)
	    curwin->w_cursor = fmark.mark;
" This was using freed memory
func Test_jump_mark_autocmd()
  next 00
  edit 0
  sargument
  au BufEnter 0 all
  sil norm 

  au! BufEnter
  bwipe!
endfunc


/**/
    530,