mirror of
https://github.com/vim/vim.git
synced 2025-09-23 03:43:49 -04:00
patch 9.0.1056: leaking memory when disassembling an object method
Problem: Leaking memory when disassembling an object method. Solution: Free the typval of the class.
This commit is contained in:
@@ -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 */
|
||||||
|
/**/
|
||||||
|
1056,
|
||||||
/**/
|
/**/
|
||||||
1055,
|
1055,
|
||||||
/**/
|
/**/
|
||||||
|
@@ -168,7 +168,7 @@ ex_class(exarg_T *eap)
|
|||||||
expr_end = expr_start;
|
expr_end = expr_start;
|
||||||
evalarg_T evalarg;
|
evalarg_T evalarg;
|
||||||
fill_evalarg_from_eap(&evalarg, eap, FALSE);
|
fill_evalarg_from_eap(&evalarg, eap, FALSE);
|
||||||
skip_expr(&expr_end, &evalarg);
|
skip_expr(&expr_end, NULL);
|
||||||
|
|
||||||
if (type == NULL)
|
if (type == NULL)
|
||||||
{
|
{
|
||||||
@@ -255,9 +255,10 @@ ex_class(exarg_T *eap)
|
|||||||
}
|
}
|
||||||
vim_free(theline);
|
vim_free(theline);
|
||||||
|
|
||||||
|
class_T *cl = NULL;
|
||||||
if (success)
|
if (success)
|
||||||
{
|
{
|
||||||
class_T *cl = ALLOC_CLEAR_ONE(class_T);
|
cl = ALLOC_CLEAR_ONE(class_T);
|
||||||
if (cl == NULL)
|
if (cl == NULL)
|
||||||
goto cleanup;
|
goto cleanup;
|
||||||
cl->class_refcount = 1;
|
cl->class_refcount = 1;
|
||||||
@@ -269,12 +270,7 @@ ex_class(exarg_T *eap)
|
|||||||
: ALLOC_MULT(objmember_T, objmembers.ga_len);
|
: ALLOC_MULT(objmember_T, objmembers.ga_len);
|
||||||
if (cl->class_name == NULL
|
if (cl->class_name == NULL
|
||||||
|| (objmembers.ga_len > 0 && cl->class_obj_members == NULL))
|
|| (objmembers.ga_len > 0 && cl->class_obj_members == NULL))
|
||||||
{
|
|
||||||
vim_free(cl->class_name);
|
|
||||||
vim_free(cl->class_obj_members);
|
|
||||||
vim_free(cl);
|
|
||||||
goto cleanup;
|
goto cleanup;
|
||||||
}
|
|
||||||
mch_memmove(cl->class_obj_members, objmembers.ga_data,
|
mch_memmove(cl->class_obj_members, objmembers.ga_data,
|
||||||
sizeof(objmember_T) * objmembers.ga_len);
|
sizeof(objmember_T) * objmembers.ga_len);
|
||||||
vim_free(objmembers.ga_data);
|
vim_free(objmembers.ga_data);
|
||||||
@@ -338,13 +334,7 @@ ex_class(exarg_T *eap)
|
|||||||
cl->class_obj_method_count = objmethods.ga_len;
|
cl->class_obj_method_count = objmethods.ga_len;
|
||||||
cl->class_obj_methods = ALLOC_MULT(ufunc_T *, objmethods.ga_len);
|
cl->class_obj_methods = ALLOC_MULT(ufunc_T *, objmethods.ga_len);
|
||||||
if (cl->class_obj_methods == NULL)
|
if (cl->class_obj_methods == NULL)
|
||||||
{
|
|
||||||
vim_free(cl->class_name);
|
|
||||||
vim_free(cl->class_obj_members);
|
|
||||||
vim_free(cl->class_obj_methods);
|
|
||||||
vim_free(cl);
|
|
||||||
goto cleanup;
|
goto cleanup;
|
||||||
}
|
|
||||||
mch_memmove(cl->class_obj_methods, objmethods.ga_data,
|
mch_memmove(cl->class_obj_methods, objmethods.ga_data,
|
||||||
sizeof(ufunc_T *) * objmethods.ga_len);
|
sizeof(ufunc_T *) * objmethods.ga_len);
|
||||||
vim_free(objmethods.ga_data);
|
vim_free(objmethods.ga_data);
|
||||||
@@ -382,6 +372,14 @@ ex_class(exarg_T *eap)
|
|||||||
}
|
}
|
||||||
|
|
||||||
cleanup:
|
cleanup:
|
||||||
|
if (cl != NULL)
|
||||||
|
{
|
||||||
|
vim_free(cl->class_name);
|
||||||
|
vim_free(cl->class_obj_members);
|
||||||
|
vim_free(cl->class_obj_methods);
|
||||||
|
vim_free(cl);
|
||||||
|
}
|
||||||
|
|
||||||
for (int i = 0; i < objmembers.ga_len; ++i)
|
for (int i = 0; i < objmembers.ga_len; ++i)
|
||||||
{
|
{
|
||||||
objmember_T *m = ((objmember_T *)objmembers.ga_data) + i;
|
objmember_T *m = ((objmember_T *)objmembers.ga_data) + i;
|
||||||
@@ -591,19 +589,16 @@ find_class_func(char_u **arg)
|
|||||||
if (eval_variable(name, len, 0, &tv, NULL, EVAL_VAR_NOAUTOLOAD) == FAIL)
|
if (eval_variable(name, len, 0, &tv, NULL, EVAL_VAR_NOAUTOLOAD) == FAIL)
|
||||||
return NULL;
|
return NULL;
|
||||||
if (tv.v_type != VAR_CLASS && tv.v_type != VAR_OBJECT)
|
if (tv.v_type != VAR_CLASS && tv.v_type != VAR_OBJECT)
|
||||||
{
|
goto fail_after_eval;
|
||||||
clear_tv(&tv);
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
class_T *cl = tv.v_type == VAR_CLASS ? tv.vval.v_class
|
class_T *cl = tv.v_type == VAR_CLASS ? tv.vval.v_class
|
||||||
: tv.vval.v_object->obj_class;
|
: tv.vval.v_object->obj_class;
|
||||||
if (cl == NULL)
|
if (cl == NULL)
|
||||||
return NULL;
|
goto fail_after_eval;
|
||||||
char_u *fname = name_end + 1;
|
char_u *fname = name_end + 1;
|
||||||
char_u *fname_end = find_name_end(fname, NULL, NULL, FNE_CHECK_START);
|
char_u *fname_end = find_name_end(fname, NULL, NULL, FNE_CHECK_START);
|
||||||
if (fname_end == fname)
|
if (fname_end == fname)
|
||||||
return NULL;
|
goto fail_after_eval;
|
||||||
len = fname_end - fname;
|
len = fname_end - fname;
|
||||||
|
|
||||||
for (int i = 0; i < cl->class_obj_method_count; ++i)
|
for (int i = 0; i < cl->class_obj_method_count; ++i)
|
||||||
@@ -613,9 +608,14 @@ find_class_func(char_u **arg)
|
|||||||
// uf_name[] only being 4 characters.
|
// uf_name[] only being 4 characters.
|
||||||
char_u *ufname = (char_u *)fp->uf_name;
|
char_u *ufname = (char_u *)fp->uf_name;
|
||||||
if (STRNCMP(fname, ufname, len) == 0 && ufname[len] == NUL)
|
if (STRNCMP(fname, ufname, len) == 0 && ufname[len] == NUL)
|
||||||
|
{
|
||||||
|
clear_tv(&tv);
|
||||||
return fp;
|
return fp;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fail_after_eval:
|
||||||
|
clear_tv(&tv);
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Reference in New Issue
Block a user