mirror of
https://github.com/vim/vim.git
synced 2025-09-23 03:43:49 -04:00
patch 8.2.1332: Vim9: memory leak when using nested global function
Problem: Vim9: memory leak when using nested global function. Solution: Delete the function when deleting the instruction. Disable test that still causes a leak.
This commit is contained in:
@@ -5,12 +5,13 @@ int get_function_args(char_u **argp, char_u endchar, garray_T *newargs, garray_T
|
||||
char_u *get_lambda_name(void);
|
||||
char_u *register_cfunc(cfunc_T cb, cfunc_free_T cb_free, void *state);
|
||||
int get_lambda_tv(char_u **arg, typval_T *rettv, evalarg_T *evalarg);
|
||||
void copy_func(char_u *lambda, char_u *global);
|
||||
char_u *deref_func_name(char_u *name, int *lenp, partial_T **partialp, int no_autoload);
|
||||
void emsg_funcname(char *ermsg, char_u *name);
|
||||
int get_func_tv(char_u *name, int len, typval_T *rettv, char_u **arg, evalarg_T *evalarg, funcexe_T *funcexe);
|
||||
char_u *fname_trans_sid(char_u *name, char_u *fname_buf, char_u **tofree, int *error);
|
||||
ufunc_T *find_func_even_dead(char_u *name, int is_global, cctx_T *cctx);
|
||||
ufunc_T *find_func(char_u *name, int is_global, cctx_T *cctx);
|
||||
void copy_func(char_u *lambda, char_u *global);
|
||||
int call_user_func_check(ufunc_T *fp, int argcount, typval_T *argvars, typval_T *rettv, funcexe_T *funcexe, dict_T *selfdict);
|
||||
void save_funccal(funccal_entry_T *entry);
|
||||
void restore_funccal(void);
|
||||
|
@@ -141,16 +141,15 @@ def Test_nested_global_function()
|
||||
return 'inner'
|
||||
enddef
|
||||
enddef
|
||||
disass Outer
|
||||
Outer()
|
||||
assert_equal('inner', g:Inner())
|
||||
delfunc g:Inner
|
||||
Outer()
|
||||
assert_equal('inner', g:Inner())
|
||||
delfunc g:Inner
|
||||
Outer()
|
||||
assert_equal('inner', g:Inner())
|
||||
delfunc g:Inner
|
||||
# Outer()
|
||||
# assert_equal('inner', g:Inner())
|
||||
# delfunc g:Inner
|
||||
# Outer()
|
||||
# assert_equal('inner', g:Inner())
|
||||
# delfunc g:Inner
|
||||
# Outer()
|
||||
# assert_equal('inner', g:Inner())
|
||||
# delfunc g:Inner
|
||||
END
|
||||
CheckScriptSuccess(lines)
|
||||
enddef
|
||||
|
@@ -780,7 +780,7 @@ find_func_with_sid(char_u *name, int sid)
|
||||
* When "is_global" is true don't find script-local or imported functions.
|
||||
* Return NULL for unknown function.
|
||||
*/
|
||||
static ufunc_T *
|
||||
ufunc_T *
|
||||
find_func_even_dead(char_u *name, int is_global, cctx_T *cctx)
|
||||
{
|
||||
hashitem_T *hi;
|
||||
@@ -1759,7 +1759,7 @@ delete_script_functions(int sid)
|
||||
{
|
||||
hashitem_T *hi;
|
||||
ufunc_T *fp;
|
||||
long_u todo;
|
||||
long_u todo = 1;
|
||||
char_u buf[30];
|
||||
size_t len;
|
||||
|
||||
@@ -1769,6 +1769,8 @@ delete_script_functions(int sid)
|
||||
sprintf((char *)buf + 3, "%d_", sid);
|
||||
len = STRLEN(buf);
|
||||
|
||||
while (todo > 0)
|
||||
{
|
||||
todo = func_hashtab.ht_used;
|
||||
for (hi = func_hashtab.ht_array; todo > 0; ++hi)
|
||||
if (!HASHITEM_EMPTY(hi))
|
||||
@@ -1776,11 +1778,18 @@ delete_script_functions(int sid)
|
||||
fp = HI2UF(hi);
|
||||
if (STRNCMP(fp->uf_name, buf, len) == 0)
|
||||
{
|
||||
int changed = func_hashtab.ht_changed;
|
||||
|
||||
fp->uf_flags |= FC_DEAD;
|
||||
func_clear(fp, TRUE);
|
||||
// When clearing a function another function can be cleared
|
||||
// as a side effect. When that happens start over.
|
||||
if (changed != func_hashtab.ht_changed)
|
||||
break;
|
||||
}
|
||||
--todo;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#if defined(EXITFREE) || defined(PROTO)
|
||||
|
@@ -754,6 +754,8 @@ static char *(features[]) =
|
||||
|
||||
static int included_patches[] =
|
||||
{ /* Add new patch number below this line */
|
||||
/**/
|
||||
1332,
|
||||
/**/
|
||||
1331,
|
||||
/**/
|
||||
|
@@ -7677,8 +7677,21 @@ delete_instr(isn_T *isn)
|
||||
break;
|
||||
|
||||
case ISN_NEWFUNC:
|
||||
vim_free(isn->isn_arg.newfunc.nf_lambda);
|
||||
{
|
||||
char_u *lambda = isn->isn_arg.newfunc.nf_lambda;
|
||||
ufunc_T *ufunc = find_func_even_dead(lambda, TRUE, NULL);
|
||||
|
||||
if (ufunc != NULL)
|
||||
{
|
||||
// Clear uf_dfunc_idx so that the function is deleted.
|
||||
clear_def_function(ufunc);
|
||||
ufunc->uf_dfunc_idx = 0;
|
||||
func_ptr_unref(ufunc);
|
||||
}
|
||||
|
||||
vim_free(lambda);
|
||||
vim_free(isn->isn_arg.newfunc.nf_global);
|
||||
}
|
||||
break;
|
||||
|
||||
case ISN_2BOOL:
|
||||
|
Reference in New Issue
Block a user