Blame SOURCES/0001-patch-8.2.4253-using-freed-memory-when-substitute-wi.patch

13ea7f
diff -up vim82/src/ex_cmds.c.cve0413 vim82/src/ex_cmds.c
13ea7f
--- vim82/src/ex_cmds.c.cve0413	2022-02-10 08:09:27.644493218 +0100
13ea7f
+++ vim82/src/ex_cmds.c	2022-02-10 08:09:27.653493168 +0100
13ea7f
@@ -3627,6 +3627,7 @@ ex_substitute(exarg_T *eap)
13ea7f
     int		save_do_all;		// remember user specified 'g' flag
13ea7f
     int		save_do_ask;		// remember user specified 'c' flag
13ea7f
     char_u	*pat = NULL, *sub = NULL;	// init for GCC
13ea7f
+    char_u	*sub_copy = NULL;
13ea7f
     int		delimiter;
13ea7f
     int		sublen;
13ea7f
     int		got_quit = FALSE;
13ea7f
@@ -3928,11 +3929,20 @@ ex_substitute(exarg_T *eap)
13ea7f
     sub_firstline = NULL;
13ea7f
 
13ea7f
     /*
13ea7f
-     * ~ in the substitute pattern is replaced with the old pattern.
13ea7f
-     * We do it here once to avoid it to be replaced over and over again.
13ea7f
-     * But don't do it when it starts with "\=", then it's an expression.
13ea7f
+     * If the substitute pattern starts with "\=" then it's an expression.
13ea7f
+     * Make a copy, a recursive function may free it.
13ea7f
+     * Otherwise, '~' in the substitute pattern is replaced with the old
13ea7f
+     * pattern.  We do it here once to avoid it to be replaced over and over
13ea7f
+     * again.
13ea7f
      */
13ea7f
-    if (!(sub[0] == '\\' && sub[1] == '='))
13ea7f
+    if (sub[0] == '\\' && sub[1] == '=')
13ea7f
+    {
13ea7f
+	sub = vim_strsave(sub);
13ea7f
+	if (sub == NULL)
13ea7f
+	    return;
13ea7f
+	sub_copy = sub;
13ea7f
+    }
13ea7f
+    else
13ea7f
 	sub = regtilde(sub, magic_isset());
13ea7f
 
13ea7f
     /*
13ea7f
@@ -4737,6 +4747,7 @@ outofmem:
13ea7f
 #endif
13ea7f
 
13ea7f
     vim_regfree(regmatch.regprog);
13ea7f
+    vim_free(sub_copy);
13ea7f
 
13ea7f
     // Restore the flag values, they can be used for ":&&".
13ea7f
     subflags.do_all = save_do_all;
13ea7f
diff -up vim82/src/testdir/test_substitute.vim.cve0413 vim82/src/testdir/test_substitute.vim
13ea7f
--- vim82/src/testdir/test_substitute.vim.cve0413	2022-02-10 08:09:27.654493162 +0100
13ea7f
+++ vim82/src/testdir/test_substitute.vim	2022-02-10 08:10:14.392230843 +0100
13ea7f
@@ -926,4 +926,21 @@ func Test_substitute_multiline_submatch(
13ea7f
   close!
13ea7f
 endfunc
13ea7f
 
13ea7f
+" This was using "old_sub" after it was freed.
13ea7f
+func Test_using_old_sub()
13ea7f
+  set compatible maxfuncdepth=10
13ea7f
+  new
13ea7f
+  call setline(1, 'some text.')
13ea7f
+  func Repl()
13ea7f
+    ~
13ea7f
+    s/
13ea7f
+  endfunc
13ea7f
+  silent!  s/\%')/\=Repl()
13ea7f
+
13ea7f
+  delfunc Repl
13ea7f
+  bwipe!
13ea7f
+  set nocompatible
13ea7f
+endfunc
13ea7f
+
13ea7f
+
13ea7f
 " vim: shiftwidth=2 sts=2 expandtab