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