changeset 31447:8cb31f7ac9e2 v9.0.1056

patch 9.0.1056: leaking memory when disassembling an object method Commit: https://github.com/vim/vim/commit/eb53350c02f620305e931ffd2ac611cc2b1a0ce9 Author: Bram Moolenaar <Bram@vim.org> Date: Wed Dec 14 15:06:11 2022 +0000 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.
author Bram Moolenaar <Bram@vim.org>
date Wed, 14 Dec 2022 16:15:04 +0100
parents a03b5695e9c5
children fd808b005553
files src/version.c src/vim9class.c
diffstat 2 files changed, 21 insertions(+), 19 deletions(-) [+]
line wrap: on
line diff
--- a/src/version.c
+++ b/src/version.c
@@ -696,6 +696,8 @@ static char *(features[]) =
 static int included_patches[] =
 {   /* Add new patch number below this line */
 /**/
+    1056,
+/**/
     1055,
 /**/
     1054,
--- a/src/vim9class.c
+++ b/src/vim9class.c
@@ -168,7 +168,7 @@ ex_class(exarg_T *eap)
 		expr_end = expr_start;
 		evalarg_T evalarg;
 		fill_evalarg_from_eap(&evalarg, eap, FALSE);
-		skip_expr(&expr_end, &evalarg);
+		skip_expr(&expr_end, NULL);
 
 		if (type == NULL)
 		{
@@ -255,9 +255,10 @@ ex_class(exarg_T *eap)
     }
     vim_free(theline);
 
+    class_T *cl = NULL;
     if (success)
     {
-	class_T *cl = ALLOC_CLEAR_ONE(class_T);
+	cl = ALLOC_CLEAR_ONE(class_T);
 	if (cl == NULL)
 	    goto cleanup;
 	cl->class_refcount = 1;
@@ -269,12 +270,7 @@ ex_class(exarg_T *eap)
 				  : ALLOC_MULT(objmember_T, objmembers.ga_len);
 	if (cl->class_name == 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;
-	}
 	mch_memmove(cl->class_obj_members, objmembers.ga_data,
 				      sizeof(objmember_T) * objmembers.ga_len);
 	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_methods = ALLOC_MULT(ufunc_T *, objmethods.ga_len);
 	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;
-	}
 	mch_memmove(cl->class_obj_methods, objmethods.ga_data,
 					sizeof(ufunc_T *) * objmethods.ga_len);
 	vim_free(objmethods.ga_data);
@@ -382,6 +372,14 @@ ex_class(exarg_T *eap)
     }
 
 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)
     {
 	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)
 	return NULL;
     if (tv.v_type != VAR_CLASS && tv.v_type != VAR_OBJECT)
-    {
-	clear_tv(&tv);
-	return NULL;
-    }
+	goto fail_after_eval;
 
     class_T *cl = tv.v_type == VAR_CLASS ? tv.vval.v_class
 						 : tv.vval.v_object->obj_class;
     if (cl == NULL)
-	return NULL;
+	goto fail_after_eval;
     char_u *fname = name_end + 1;
     char_u *fname_end = find_name_end(fname, NULL, NULL, FNE_CHECK_START);
     if (fname_end == fname)
-	return NULL;
+	goto fail_after_eval;
     len = fname_end - fname;
 
     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.
 	char_u *ufname = (char_u *)fp->uf_name;
 	if (STRNCMP(fname, ufname, len) == 0 && ufname[len] == NUL)
+	{
+	    clear_tv(&tv);
 	    return fp;
+	}
     }
 
+fail_after_eval:
+    clear_tv(&tv);
     return NULL;
 }