mirror of
https://github.com/neovim/neovim.git
synced 2025-09-29 14:38:32 +00:00
vim-patch:9.0.0047: using freed memory with recursive substitute (#19457)
Problem: Using freed memory with recursive substitute.
Solution: Always make a copy for reg_prev_sub.
32acf1f1a7
This commit is contained in:
@@ -3644,7 +3644,6 @@ static int do_sub(exarg_T *eap, proftime_T timeout, long cmdpreview_ns, handle_T
|
|||||||
|
|
||||||
assert(sub != NULL);
|
assert(sub != NULL);
|
||||||
|
|
||||||
bool sub_needs_free = false;
|
|
||||||
char *sub_copy = NULL;
|
char *sub_copy = NULL;
|
||||||
|
|
||||||
// If the substitute pattern starts with "\=" then it's an expression.
|
// If the substitute pattern starts with "\=" then it's an expression.
|
||||||
@@ -3656,11 +3655,12 @@ static int do_sub(exarg_T *eap, proftime_T timeout, long cmdpreview_ns, handle_T
|
|||||||
sub = xstrdup(sub);
|
sub = xstrdup(sub);
|
||||||
sub_copy = sub;
|
sub_copy = sub;
|
||||||
} else {
|
} else {
|
||||||
char *source = sub;
|
char *newsub = (char *)regtilde((char_u *)sub, p_magic, cmdpreview);
|
||||||
sub = (char *)regtilde((char_u *)sub, p_magic, cmdpreview);
|
if (newsub != sub) {
|
||||||
// When previewing, the new pattern allocated by regtilde() needs to be freed
|
// newsub was allocated, free it later.
|
||||||
// in this function because it will not be used or freed by regtilde() later.
|
sub_copy = newsub;
|
||||||
sub_needs_free = cmdpreview && sub != source;
|
sub = newsub;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
bool cmdheight0 = p_ch < 1 && !ui_has(kUIMessages);
|
bool cmdheight0 = p_ch < 1 && !ui_has(kUIMessages);
|
||||||
@@ -4459,9 +4459,6 @@ skip:
|
|||||||
|
|
||||||
vim_regfree(regmatch.regprog);
|
vim_regfree(regmatch.regprog);
|
||||||
xfree(sub_copy);
|
xfree(sub_copy);
|
||||||
if (sub_needs_free) {
|
|
||||||
xfree(sub);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Restore the flag values, they can be used for ":&&".
|
// Restore the flag values, they can be used for ":&&".
|
||||||
subflags.do_all = save_do_all;
|
subflags.do_all = save_do_all;
|
||||||
|
@@ -1587,13 +1587,11 @@ char_u *regtilde(char_u *source, int magic, bool preview)
|
|||||||
|
|
||||||
// Only change reg_prev_sub when not previewing.
|
// Only change reg_prev_sub when not previewing.
|
||||||
if (!preview) {
|
if (!preview) {
|
||||||
|
// Store a copy of newsub in reg_prev_sub. It is always allocated,
|
||||||
|
// because recursive calls may make the returned string invalid.
|
||||||
xfree(reg_prev_sub);
|
xfree(reg_prev_sub);
|
||||||
if (newsub != source) { // newsub was allocated, just keep it
|
|
||||||
reg_prev_sub = newsub;
|
|
||||||
} else { // no ~ found, need to save newsub
|
|
||||||
reg_prev_sub = vim_strsave(newsub);
|
reg_prev_sub = vim_strsave(newsub);
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
return newsub;
|
return newsub;
|
||||||
}
|
}
|
||||||
|
@@ -1027,4 +1027,15 @@ func Test_using_invalid_visual_position()
|
|||||||
bwipe!
|
bwipe!
|
||||||
endfunc
|
endfunc
|
||||||
|
|
||||||
|
func Test_recursive_substitute_expr()
|
||||||
|
new
|
||||||
|
func Repl()
|
||||||
|
s
|
||||||
|
endfunc
|
||||||
|
silent! s/\%')/~\=Repl()
|
||||||
|
|
||||||
|
bwipe!
|
||||||
|
delfunc Repl
|
||||||
|
endfunc
|
||||||
|
|
||||||
" vim: shiftwidth=2 sts=2 expandtab
|
" vim: shiftwidth=2 sts=2 expandtab
|
||||||
|
Reference in New Issue
Block a user