mirror of
https://github.com/vim/vim.git
synced 2025-09-25 03:54:15 -04:00
patch 8.2.3812: Vim9: leaking memory in numbered function test
Problem: Vim9: leaking memory in numbered function test. Solution: Skip "g:" when checking for numbered function. Clean up after errors properly.
This commit is contained in:
@@ -2135,6 +2135,16 @@ cleanup_function_call(funccall_T *fc)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Return TRUE if "name" is a numbered function, ignoring a "g:" prefix.
|
||||||
|
*/
|
||||||
|
static int
|
||||||
|
numbered_function(char_u *name)
|
||||||
|
{
|
||||||
|
return isdigit(*name)
|
||||||
|
|| (name[0] == 'g' && name[1] == ':' && isdigit(name[2]));
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* There are two kinds of function names:
|
* There are two kinds of function names:
|
||||||
* 1. ordinary names, function defined with :function or :def
|
* 1. ordinary names, function defined with :function or :def
|
||||||
@@ -2146,7 +2156,7 @@ cleanup_function_call(funccall_T *fc)
|
|||||||
int
|
int
|
||||||
func_name_refcount(char_u *name)
|
func_name_refcount(char_u *name)
|
||||||
{
|
{
|
||||||
return isdigit(*name) || *name == '<';
|
return numbered_function(name) || *name == '<';
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@@ -3956,6 +3966,8 @@ define_function(exarg_T *eap, char_u *name_arg)
|
|||||||
int flags = 0;
|
int flags = 0;
|
||||||
char_u *ret_type = NULL;
|
char_u *ret_type = NULL;
|
||||||
ufunc_T *fp = NULL;
|
ufunc_T *fp = NULL;
|
||||||
|
int fp_allocated = FALSE;
|
||||||
|
int free_fp = FALSE;
|
||||||
int overwrite = FALSE;
|
int overwrite = FALSE;
|
||||||
dictitem_T *v;
|
dictitem_T *v;
|
||||||
funcdict_T fudi;
|
funcdict_T fudi;
|
||||||
@@ -4460,6 +4472,7 @@ define_function(exarg_T *eap, char_u *name_arg)
|
|||||||
fp = alloc_clear(offsetof(ufunc_T, uf_name) + STRLEN(name) + 1);
|
fp = alloc_clear(offsetof(ufunc_T, uf_name) + STRLEN(name) + 1);
|
||||||
if (fp == NULL)
|
if (fp == NULL)
|
||||||
goto erret;
|
goto erret;
|
||||||
|
fp_allocated = TRUE;
|
||||||
|
|
||||||
if (fudi.fd_dict != NULL)
|
if (fudi.fd_dict != NULL)
|
||||||
{
|
{
|
||||||
@@ -4490,21 +4503,6 @@ define_function(exarg_T *eap, char_u *name_arg)
|
|||||||
// behave like "dict" was used
|
// behave like "dict" was used
|
||||||
flags |= FC_DICT;
|
flags |= FC_DICT;
|
||||||
}
|
}
|
||||||
|
|
||||||
// insert the new function in the function list
|
|
||||||
set_ufunc_name(fp, name);
|
|
||||||
if (overwrite)
|
|
||||||
{
|
|
||||||
hi = hash_find(&func_hashtab, name);
|
|
||||||
hi->hi_key = UF2HIKEY(fp);
|
|
||||||
}
|
|
||||||
else if (hash_add(&func_hashtab, UF2HIKEY(fp)) == FAIL)
|
|
||||||
{
|
|
||||||
vim_free(fp);
|
|
||||||
fp = NULL;
|
|
||||||
goto erret;
|
|
||||||
}
|
|
||||||
fp->uf_refcount = 1;
|
|
||||||
}
|
}
|
||||||
fp->uf_args = newargs;
|
fp->uf_args = newargs;
|
||||||
fp->uf_def_args = default_args;
|
fp->uf_def_args = default_args;
|
||||||
@@ -4527,7 +4525,8 @@ define_function(exarg_T *eap, char_u *name_arg)
|
|||||||
if (parse_argument_types(fp, &argtypes, varargs) == FAIL)
|
if (parse_argument_types(fp, &argtypes, varargs) == FAIL)
|
||||||
{
|
{
|
||||||
SOURCING_LNUM = lnum_save;
|
SOURCING_LNUM = lnum_save;
|
||||||
goto errret_2;
|
free_fp = fp_allocated;
|
||||||
|
goto erret;
|
||||||
}
|
}
|
||||||
varargs = FALSE;
|
varargs = FALSE;
|
||||||
|
|
||||||
@@ -4535,6 +4534,7 @@ define_function(exarg_T *eap, char_u *name_arg)
|
|||||||
if (parse_return_type(fp, ret_type) == FAIL)
|
if (parse_return_type(fp, ret_type) == FAIL)
|
||||||
{
|
{
|
||||||
SOURCING_LNUM = lnum_save;
|
SOURCING_LNUM = lnum_save;
|
||||||
|
free_fp = fp_allocated;
|
||||||
goto erret;
|
goto erret;
|
||||||
}
|
}
|
||||||
SOURCING_LNUM = lnum_save;
|
SOURCING_LNUM = lnum_save;
|
||||||
@@ -4542,7 +4542,25 @@ define_function(exarg_T *eap, char_u *name_arg)
|
|||||||
else
|
else
|
||||||
fp->uf_def_status = UF_NOT_COMPILED;
|
fp->uf_def_status = UF_NOT_COMPILED;
|
||||||
|
|
||||||
|
if (fp_allocated)
|
||||||
|
{
|
||||||
|
// insert the new function in the function list
|
||||||
|
set_ufunc_name(fp, name);
|
||||||
|
if (overwrite)
|
||||||
|
{
|
||||||
|
hi = hash_find(&func_hashtab, name);
|
||||||
|
hi->hi_key = UF2HIKEY(fp);
|
||||||
|
}
|
||||||
|
else if (hash_add(&func_hashtab, UF2HIKEY(fp)) == FAIL)
|
||||||
|
{
|
||||||
|
free_fp = TRUE;
|
||||||
|
goto erret;
|
||||||
|
}
|
||||||
|
fp->uf_refcount = 1;
|
||||||
|
}
|
||||||
|
|
||||||
fp->uf_lines = newlines;
|
fp->uf_lines = newlines;
|
||||||
|
newlines.ga_data = NULL;
|
||||||
if ((flags & FC_CLOSURE) != 0)
|
if ((flags & FC_CLOSURE) != 0)
|
||||||
{
|
{
|
||||||
if (register_closure(fp) == FAIL)
|
if (register_closure(fp) == FAIL)
|
||||||
@@ -4593,6 +4611,11 @@ errret_2:
|
|||||||
ga_clear_strings(&newlines);
|
ga_clear_strings(&newlines);
|
||||||
if (fp != NULL)
|
if (fp != NULL)
|
||||||
VIM_CLEAR(fp->uf_arg_types);
|
VIM_CLEAR(fp->uf_arg_types);
|
||||||
|
if (free_fp)
|
||||||
|
{
|
||||||
|
vim_free(fp);
|
||||||
|
fp = NULL;
|
||||||
|
}
|
||||||
ret_free:
|
ret_free:
|
||||||
ga_clear_strings(&argtypes);
|
ga_clear_strings(&argtypes);
|
||||||
vim_free(line_to_free);
|
vim_free(line_to_free);
|
||||||
@@ -4813,7 +4836,7 @@ ex_delfunction(exarg_T *eap)
|
|||||||
if (eap->nextcmd != NULL)
|
if (eap->nextcmd != NULL)
|
||||||
*p = NUL;
|
*p = NUL;
|
||||||
|
|
||||||
if (isdigit(*name) && fudi.fd_dict == NULL)
|
if (numbered_function(name) && fudi.fd_dict == NULL)
|
||||||
{
|
{
|
||||||
if (!eap->skip)
|
if (!eap->skip)
|
||||||
semsg(_(e_invarg2), eap->arg);
|
semsg(_(e_invarg2), eap->arg);
|
||||||
@@ -4881,7 +4904,7 @@ func_unref(char_u *name)
|
|||||||
if (name == NULL || !func_name_refcount(name))
|
if (name == NULL || !func_name_refcount(name))
|
||||||
return;
|
return;
|
||||||
fp = find_func(name, FALSE, NULL);
|
fp = find_func(name, FALSE, NULL);
|
||||||
if (fp == NULL && isdigit(*name))
|
if (fp == NULL && numbered_function(name))
|
||||||
{
|
{
|
||||||
#ifdef EXITFREE
|
#ifdef EXITFREE
|
||||||
if (!entered_free_all_mem)
|
if (!entered_free_all_mem)
|
||||||
@@ -4924,7 +4947,7 @@ func_ref(char_u *name)
|
|||||||
fp = find_func(name, FALSE, NULL);
|
fp = find_func(name, FALSE, NULL);
|
||||||
if (fp != NULL)
|
if (fp != NULL)
|
||||||
++fp->uf_refcount;
|
++fp->uf_refcount;
|
||||||
else if (isdigit(*name))
|
else if (numbered_function(name))
|
||||||
// Only give an error for a numbered function.
|
// Only give an error for a numbered function.
|
||||||
// Fail silently, when named or lambda function isn't found.
|
// Fail silently, when named or lambda function isn't found.
|
||||||
internal_error("func_ref()");
|
internal_error("func_ref()");
|
||||||
|
@@ -749,6 +749,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 */
|
||||||
|
/**/
|
||||||
|
3812,
|
||||||
/**/
|
/**/
|
||||||
3811,
|
3811,
|
||||||
/**/
|
/**/
|
||||||
|
Reference in New Issue
Block a user