mirror of
https://github.com/vim/vim.git
synced 2025-09-26 04:04:07 -04:00
patch 9.0.0875: using freed memory when executing delfunc at more prompt
Problem: Using freed memory when executing delfunc at the more prompt. Solution: Check function list not changed in another place. (closes #11437)
This commit is contained in:
@@ -3026,4 +3026,31 @@ func Test_virtcol()
|
|||||||
bwipe!
|
bwipe!
|
||||||
endfunc
|
endfunc
|
||||||
|
|
||||||
|
func Test_delfunc_while_listing()
|
||||||
|
CheckRunVimInTerminal
|
||||||
|
|
||||||
|
let lines =<< trim END
|
||||||
|
set nocompatible
|
||||||
|
for i in range(1, 999)
|
||||||
|
exe 'func ' .. 'MyFunc' .. i .. '()'
|
||||||
|
endfunc
|
||||||
|
endfor
|
||||||
|
au CmdlineLeave : call timer_start(0, {-> execute('delfunc MyFunc622')})
|
||||||
|
END
|
||||||
|
call writefile(lines, 'Xfunctionclear', 'D')
|
||||||
|
let buf = RunVimInTerminal('-S Xfunctionclear', {'rows': 12})
|
||||||
|
|
||||||
|
" This was using freed memory. The height of the terminal must be so that
|
||||||
|
" the next function to be listed with "j" is the one that is deleted in the
|
||||||
|
" timer callback, tricky!
|
||||||
|
call term_sendkeys(buf, ":func /MyFunc\<CR>")
|
||||||
|
call TermWait(buf, 50)
|
||||||
|
call term_sendkeys(buf, "j")
|
||||||
|
call TermWait(buf, 50)
|
||||||
|
call term_sendkeys(buf, "\<CR>")
|
||||||
|
|
||||||
|
call StopVimInTerminal(buf)
|
||||||
|
endfunc
|
||||||
|
|
||||||
|
|
||||||
" vim: shiftwidth=2 sts=2 expandtab
|
" vim: shiftwidth=2 sts=2 expandtab
|
||||||
|
@@ -3792,15 +3792,36 @@ printable_func_name(ufunc_T *fp)
|
|||||||
return fp->uf_name_exp != NULL ? fp->uf_name_exp : fp->uf_name;
|
return fp->uf_name_exp != NULL ? fp->uf_name_exp : fp->uf_name;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* When "prev_ht_changed" does not equal "ht_changed" give an error and return
|
||||||
|
* TRUE. Otherwise return FALSE.
|
||||||
|
*/
|
||||||
|
static int
|
||||||
|
function_list_modified(int prev_ht_changed)
|
||||||
|
{
|
||||||
|
if (prev_ht_changed != func_hashtab.ht_changed)
|
||||||
|
{
|
||||||
|
emsg(_(e_function_list_was_modified));
|
||||||
|
return TRUE;
|
||||||
|
}
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* List the head of the function: "function name(arg1, arg2)".
|
* List the head of the function: "function name(arg1, arg2)".
|
||||||
*/
|
*/
|
||||||
static void
|
static int
|
||||||
list_func_head(ufunc_T *fp, int indent)
|
list_func_head(ufunc_T *fp, int indent)
|
||||||
{
|
{
|
||||||
|
int prev_ht_changed = func_hashtab.ht_changed;
|
||||||
int j;
|
int j;
|
||||||
|
|
||||||
msg_start();
|
msg_start();
|
||||||
|
|
||||||
|
// a timer at the more prompt may have deleted the function
|
||||||
|
if (function_list_modified(prev_ht_changed))
|
||||||
|
return FAIL;
|
||||||
|
|
||||||
if (indent)
|
if (indent)
|
||||||
msg_puts(" ");
|
msg_puts(" ");
|
||||||
if (fp->uf_def_status != UF_NOT_COMPILED)
|
if (fp->uf_def_status != UF_NOT_COMPILED)
|
||||||
@@ -3877,6 +3898,8 @@ list_func_head(ufunc_T *fp, int indent)
|
|||||||
msg_clr_eos();
|
msg_clr_eos();
|
||||||
if (p_verbose > 0)
|
if (p_verbose > 0)
|
||||||
last_set_msg(fp->uf_script_ctx);
|
last_set_msg(fp->uf_script_ctx);
|
||||||
|
|
||||||
|
return OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@@ -4315,7 +4338,7 @@ save_function_name(
|
|||||||
void
|
void
|
||||||
list_functions(regmatch_T *regmatch)
|
list_functions(regmatch_T *regmatch)
|
||||||
{
|
{
|
||||||
int changed = func_hashtab.ht_changed;
|
int prev_ht_changed = func_hashtab.ht_changed;
|
||||||
long_u todo = func_hashtab.ht_used;
|
long_u todo = func_hashtab.ht_used;
|
||||||
hashitem_T *hi;
|
hashitem_T *hi;
|
||||||
|
|
||||||
@@ -4333,12 +4356,10 @@ list_functions(regmatch_T *regmatch)
|
|||||||
: !isdigit(*fp->uf_name)
|
: !isdigit(*fp->uf_name)
|
||||||
&& vim_regexec(regmatch, fp->uf_name, 0)))
|
&& vim_regexec(regmatch, fp->uf_name, 0)))
|
||||||
{
|
{
|
||||||
list_func_head(fp, FALSE);
|
if (list_func_head(fp, FALSE) == FAIL)
|
||||||
if (changed != func_hashtab.ht_changed)
|
return;
|
||||||
{
|
if (function_list_modified(prev_ht_changed))
|
||||||
emsg(_(e_function_list_was_modified));
|
|
||||||
return;
|
return;
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -4542,28 +4563,39 @@ define_function(exarg_T *eap, char_u *name_arg, garray_T *lines_to_free)
|
|||||||
|
|
||||||
if (fp != NULL)
|
if (fp != NULL)
|
||||||
{
|
{
|
||||||
list_func_head(fp, TRUE);
|
// Check no function was added or removed from a timer, e.g. at
|
||||||
for (j = 0; j < fp->uf_lines.ga_len && !got_int; ++j)
|
// the more prompt. "fp" may then be invalid.
|
||||||
|
int prev_ht_changed = func_hashtab.ht_changed;
|
||||||
|
|
||||||
|
if (list_func_head(fp, TRUE) == OK)
|
||||||
{
|
{
|
||||||
if (FUNCLINE(fp, j) == NULL)
|
for (j = 0; j < fp->uf_lines.ga_len && !got_int; ++j)
|
||||||
continue;
|
{
|
||||||
msg_putchar('\n');
|
if (FUNCLINE(fp, j) == NULL)
|
||||||
msg_outnum((long)(j + 1));
|
continue;
|
||||||
if (j < 9)
|
msg_putchar('\n');
|
||||||
msg_putchar(' ');
|
msg_outnum((long)(j + 1));
|
||||||
if (j < 99)
|
if (j < 9)
|
||||||
msg_putchar(' ');
|
msg_putchar(' ');
|
||||||
msg_prt_line(FUNCLINE(fp, j), FALSE);
|
if (j < 99)
|
||||||
out_flush(); // show a line at a time
|
msg_putchar(' ');
|
||||||
ui_breakcheck();
|
if (function_list_modified(prev_ht_changed))
|
||||||
}
|
break;
|
||||||
if (!got_int)
|
msg_prt_line(FUNCLINE(fp, j), FALSE);
|
||||||
{
|
out_flush(); // show a line at a time
|
||||||
msg_putchar('\n');
|
ui_breakcheck();
|
||||||
if (fp->uf_def_status != UF_NOT_COMPILED)
|
}
|
||||||
msg_puts(" enddef");
|
if (!got_int)
|
||||||
else
|
{
|
||||||
msg_puts(" endfunction");
|
msg_putchar('\n');
|
||||||
|
if (!function_list_modified(prev_ht_changed))
|
||||||
|
{
|
||||||
|
if (fp->uf_def_status != UF_NOT_COMPILED)
|
||||||
|
msg_puts(" enddef");
|
||||||
|
else
|
||||||
|
msg_puts(" endfunction");
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
|
@@ -695,6 +695,8 @@ static char *(features[]) =
|
|||||||
|
|
||||||
static int included_patches[] =
|
static int included_patches[] =
|
||||||
{ /* Add new patch number below this line */
|
{ /* Add new patch number below this line */
|
||||||
|
/**/
|
||||||
|
875,
|
||||||
/**/
|
/**/
|
||||||
874,
|
874,
|
||||||
/**/
|
/**/
|
||||||
|
Reference in New Issue
Block a user