CVE-2022-2042: Use After Free (CWE-416)
value: Use After Free in GitHub repository vim/vim prior to 8.2.
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-06-10T19:15Z
Repository: https://github.com/vim/vim
Language: C
Files changed: src/spell.c, src/testdir/test_spell_utf8.vim, src/version.c
Commit date: 2022-06-09 19:54:24 +0100
Commit message: patch 8.2.5072: using uninitialized value and freed memory in spell command

Problem:    Using uninitialized value and freed memory in spell command.
Solution:   Initialize "attr".  Check for empty line early.

Diff: diff --git a/src/spell.c b/src/spell.c
index 48a2203e3f04..d866a2df7265 100644
--- a/src/spell.c
+++ b/src/spell.c
@@ -1273,11 +1273,11 @@ spell_move_to(
     pos_T	found_pos;
     int		found_len = 0;
     char_u	*line;
     char_u	*p;
     char_u	*endp;
-    hlf_T	attr;
+    hlf_T	attr = 0;
     int		len;
 #ifdef FEAT_SYN_HL
     int		has_syntax = syntax_present(wp);
 #endif
     int		col;
@@ -1306,10 +1306,12 @@ spell_move_to(
     lnum = wp->w_cursor.lnum;
     CLEAR_POS(&found_pos);
 
     while (!got_int)
     {
+	int empty_line;
+
 	line = ml_get_buf(wp->w_buffer, lnum, FALSE);
 
 	len = (int)STRLEN(line);
 	if (buflen < len + MAXWLEN + 2)
 	{
@@ -1338,11 +1340,13 @@ spell_move_to(
 	    // one.
 	    line = ml_get_buf(wp->w_buffer, lnum, FALSE);
 	}
 
 	// Copy the line into "buf" and append the start of the next line if
-	// possible.
+	// possible.  Note: this ml_get_buf() may make "line" invalid, check
+	// for empty line first.
+	empty_line = *skipwhite(line) == NUL;
 	STRCPY(buf, line);
 	if (lnum < wp->w_buffer->b_ml.ml_line_count)
 	    spell_cat_line(buf + STRLEN(buf),
 			  ml_get_buf(wp->w_buffer, lnum + 1, FALSE), MAXWLEN);
 
@@ -1485,11 +1489,11 @@ spell_move_to(
 
 	    // Capcol skips over the inserted space.
 	    --capcol;
 
 	    // But after empty line check first word in next line
-	    if (*skipwhite(line) == NUL)
+	    if (empty_line)
 		capcol = 0;
 	}
 
 	line_breakcheck();
     }
diff --git a/src/testdir/test_spell_utf8.vim b/src/testdir/test_spell_utf8.vim
index ef08f953521c..f9f85a63ae99 100644
--- a/src/testdir/test_spell_utf8.vim
+++ b/src/testdir/test_spell_utf8.vim
@@ -800,7 +800,22 @@ func Test_word_index()
   " clear the word list
   set enc=utf-8
   call delete('Xtmpfile')
 endfunc
 
+func Test_check_empty_line()
+  " This was using freed memory
+  enew
+  spellgood! ﬂ
+  norm z=
+  norm yy
+  sil! norm P]svc
+  norm P]s
+
+  " set 'encoding' to clear the wordt list
+  set enc=latin1
+  set enc=utf-8
+  bwipe!
+endfunc
+
 
 " vim: shiftwidth=2 sts=2 expandtab
diff --git a/src/version.c b/src/version.c
index ebfd0d45feef..8f5a4ff71b60 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 */
+/**/
+    5072,
 /**/
     5071,
 /**/
     5070,
 /**/

Vulnerable code:     hlf_T	attr;
	// possible.
	    if (*skipwhite(line) == NUL)
Fixed code:     hlf_T	attr = 0;
	int empty_line;

	// possible.  Note: this ml_get_buf() may make "line" invalid, check
	// for empty line first.
	empty_line = *skipwhite(line) == NUL;
	    if (empty_line)
func Test_check_empty_line()
  " This was using freed memory
  enew
  spellgood! ﬂ
  norm z=
  norm yy
  sil! norm P]svc
  norm P]s

  " set 'encoding' to clear the wordt list
  set enc=latin1
  set enc=utf-8
  bwipe!
endfunc

/**/
    5072,