diff options
author | zeertzjq <zeertzjq@outlook.com> | 2022-04-04 13:02:32 +0800 |
---|---|---|
committer | GitHub <noreply@github.com> | 2022-04-04 13:02:32 +0800 |
commit | daa8ac051d9e641cb708af5ae2ffd571f5abbc44 (patch) | |
tree | 410fdd3af60b0ba3af8a67edde01818ba6a84a89 | |
parent | db13f105d62e868997e61d8cef921fbebb312ddc (diff) | |
parent | bbfc44e255ec6d1a6ced68dde64ff5d3c68b9ceb (diff) | |
download | rneovim-daa8ac051d9e641cb708af5ae2ffd571f5abbc44.tar.gz rneovim-daa8ac051d9e641cb708af5ae2ffd571f5abbc44.tar.bz2 rneovim-daa8ac051d9e641cb708af5ae2ffd571f5abbc44.zip |
Merge pull request #17991 from zeertzjq/vim-8.2.4253
vim-patch:8.2.4253: using freed memory when substitute with function call
-rw-r--r-- | src/nvim/ex_cmds.c | 25 | ||||
-rw-r--r-- | src/nvim/regexp.c | 4 | ||||
-rw-r--r-- | src/nvim/shada.c | 2 | ||||
-rw-r--r-- | src/nvim/testdir/test_substitute.vim | 18 |
4 files changed, 37 insertions, 12 deletions
diff --git a/src/nvim/ex_cmds.c b/src/nvim/ex_cmds.c index 71b3517adc..65cb544efd 100644 --- a/src/nvim/ex_cmds.c +++ b/src/nvim/ex_cmds.c @@ -3627,15 +3627,22 @@ static buf_T *do_sub(exarg_T *eap, proftime_T timeout, bool do_buf_event, handle 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. assert(sub != NULL); bool sub_needs_free = false; - if (!(sub[0] == '\\' && sub[1] == '=')) { + char_u *sub_copy = NULL; + + // 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] == '=') { + sub = vim_strsave(sub); + sub_copy = sub; + } else { char_u *source = sub; - sub = regtilde(sub, p_magic); + sub = regtilde(sub, p_magic, preview); // When previewing, the new pattern allocated by regtilde() needs to be freed // in this function because it will not be used or freed by regtilde() later. sub_needs_free = preview && sub != source; @@ -4412,6 +4419,10 @@ skip: } vim_regfree(regmatch.regprog); + xfree(sub_copy); + if (sub_needs_free) { + xfree(sub); + } // Restore the flag values, they can be used for ":&&". subflags.do_all = save_do_all; @@ -4444,10 +4455,6 @@ skip: kv_destroy(preview_lines.subresults); - if (sub_needs_free) { - xfree(sub); - } - return preview_buf; #undef ADJUST_SUB_FIRSTLNUM #undef PUSH_PREVIEW_LINES diff --git a/src/nvim/regexp.c b/src/nvim/regexp.c index 53add57736..9a04cc428a 100644 --- a/src/nvim/regexp.c +++ b/src/nvim/regexp.c @@ -1531,7 +1531,7 @@ static fptr_T do_Lower(int *d, int c) * * The tildes are parsed once before the first call to vim_regsub(). */ -char_u *regtilde(char_u *source, int magic) +char_u *regtilde(char_u *source, int magic, bool preview) { char_u *newsub = source; char_u *tmpsub; @@ -1576,7 +1576,7 @@ char_u *regtilde(char_u *source, int magic) } // Only change reg_prev_sub when not previewing. - if (!(State & CMDPREVIEW)) { + if (!preview) { xfree(reg_prev_sub); if (newsub != source) { // newsub was allocated, just keep it reg_prev_sub = newsub; diff --git a/src/nvim/shada.c b/src/nvim/shada.c index b909888783..6c0add87d3 100644 --- a/src/nvim/shada.c +++ b/src/nvim/shada.c @@ -1238,7 +1238,7 @@ static void shada_read(ShaDaReadDef *const sd_reader, const int flags) // string is close to useless: you can only use it with :& or :~ and // that’s all because s//~ is not available until the first call to // regtilde. Vim was not calling this for some reason. - (void)(char *)regtilde((char_u *)cur_entry.data.sub_string.sub, p_magic); + (void)(char *)regtilde((char_u *)cur_entry.data.sub_string.sub, p_magic, false); // Do not free shada entry: its allocated memory was saved above. break; case kSDItemHistoryEntry: diff --git a/src/nvim/testdir/test_substitute.vim b/src/nvim/testdir/test_substitute.vim index 9710a7ab84..86fd0147a5 100644 --- a/src/nvim/testdir/test_substitute.vim +++ b/src/nvim/testdir/test_substitute.vim @@ -819,4 +819,22 @@ func Test_substitute_skipped_range() bwipe! endfunc +" This was using "old_sub" after it was freed. +func Test_using_old_sub() + " set compatible maxfuncdepth=10 + set 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 |