mirror of
https://github.com/neovim/neovim.git
synced 2024-12-31 17:13:26 -07:00
Merge pull request #17991 from zeertzjq/vim-8.2.4253
vim-patch:8.2.4253: using freed memory when substitute with function call
This commit is contained in:
commit
daa8ac051d
@ -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
|
||||
|
@ -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;
|
||||
|
@ -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:
|
||||
|
@ -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
|
||||
|
Loading…
Reference in New Issue
Block a user