Skip to content

Commit

Permalink
patch 8.2.4253: using freed memory when substitute with function call
Browse files Browse the repository at this point in the history
Problem:    Using freed memory when substitute uses a recursive function call.
Solution:   Make a copy of the substitute text.
  • Loading branch information
brammool committed Jan 29, 2022
1 parent 4dc0dd8 commit 37f4795
Show file tree
Hide file tree
Showing 3 changed files with 34 additions and 4 deletions.
19 changes: 15 additions & 4 deletions src/ex_cmds.c
Expand Up @@ -3687,6 +3687,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;
Expand Down Expand Up @@ -3980,11 +3981,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());

/*
Expand Down Expand Up @@ -4790,6 +4800,7 @@ ex_substitute(exarg_T *eap)
#endif

vim_regfree(regmatch.regprog);
vim_free(sub_copy);

// Restore the flag values, they can be used for ":&&".
subflags.do_all = save_do_all;
Expand Down
17 changes: 17 additions & 0 deletions src/testdir/test_substitute.vim
Expand Up @@ -980,4 +980,21 @@ func Test_substitute_gdefault()
bw!
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
2 changes: 2 additions & 0 deletions src/version.c
Expand Up @@ -750,6 +750,8 @@ static char *(features[]) =

static int included_patches[] =
{ /* Add new patch number below this line */
/**/
4253,
/**/
4252,
/**/
Expand Down

0 comments on commit 37f4795

Please sign in to comment.