changeset 20657:a1e6d9353736 v8.2.0882

patch 8.2.0882: leaking memory when using reduce() Commit: https://github.com/vim/vim/commit/48b1c21809553d3463b5ed6c2b3bc6d335663bb6 Author: Bram Moolenaar <Bram@vim.org> Date: Mon Jun 1 20:11:02 2020 +0200 patch 8.2.0882: leaking memory when using reduce() Problem: Leaking memory when using reduce(). Solution: Free the intermediate value.
author Bram Moolenaar <Bram@vim.org>
date Mon, 01 Jun 2020 20:15:04 +0200
parents d9b945841cba
children 0cbef5a89050
files src/list.c src/version.c
diffstat 2 files changed, 22 insertions(+), 13 deletions(-) [+]
line wrap: on
line diff
--- a/src/list.c
+++ b/src/list.c
@@ -2311,7 +2311,7 @@ f_reverse(typval_T *argvars, typval_T *r
     void
 f_reduce(typval_T *argvars, typval_T *rettv)
 {
-    typval_T	accum;
+    typval_T	initial;
     char_u	*func_name;
     partial_T   *partial = NULL;
     funcexe_T	funcexe;
@@ -2343,6 +2343,7 @@ f_reduce(typval_T *argvars, typval_T *re
     {
 	list_T	    *l = argvars[0].vval.v_list;
 	listitem_T  *li = NULL;
+	int	    r;
 
 	CHECK_LIST_MATERIALIZE(l);
 	if (argvars[2].v_type == VAR_UNKNOWN)
@@ -2352,24 +2353,26 @@ f_reduce(typval_T *argvars, typval_T *re
 		semsg(_(e_reduceempty), "List");
 		return;
 	    }
-	    accum = l->lv_first->li_tv;
+	    initial = l->lv_first->li_tv;
 	    li = l->lv_first->li_next;
 	}
 	else
 	{
-	    accum = argvars[2];
+	    initial = argvars[2];
 	    if (l != NULL)
 		li = l->lv_first;
 	}
 
-	copy_tv(&accum, rettv);
+	copy_tv(&initial, rettv);
 	for ( ; li != NULL; li = li->li_next)
 	{
-	    argv[0] = accum;
+	    argv[0] = *rettv;
 	    argv[1] = li->li_tv;
-	    if (call_func(func_name, -1, rettv, 2, argv, &funcexe) == FAIL)
+	    rettv->v_type = VAR_UNKNOWN;
+	    r = call_func(func_name, -1, rettv, 2, argv, &funcexe);
+	    clear_tv(&argv[0]);
+	    if (r == FAIL)
 		return;
-	    accum = *rettv;
 	}
     }
     else
@@ -2384,27 +2387,31 @@ f_reduce(typval_T *argvars, typval_T *re
 		semsg(_(e_reduceempty), "Blob");
 		return;
 	    }
-	    accum.v_type = VAR_NUMBER;
-	    accum.vval.v_number = blob_get(b, 0);
+	    initial.v_type = VAR_NUMBER;
+	    initial.vval.v_number = blob_get(b, 0);
 	    i = 1;
 	}
+	else if (argvars[2].v_type != VAR_NUMBER)
+	{
+	    emsg(_(e_number_exp));
+	    return;
+	}
 	else
 	{
-	    accum = argvars[2];
+	    initial = argvars[2];
 	    i = 0;
 	}
 
-	copy_tv(&accum, rettv);
+	copy_tv(&initial, rettv);
 	if (b != NULL)
 	{
 	    for ( ; i < b->bv_ga.ga_len; i++)
 	    {
-		argv[0] = accum;
+		argv[0] = *rettv;
 		argv[1].v_type = VAR_NUMBER;
 		argv[1].vval.v_number = blob_get(b, i);
 		if (call_func(func_name, -1, rettv, 2, argv, &funcexe) == FAIL)
 		    return;
-		accum = *rettv;
 	    }
 	}
     }
--- a/src/version.c
+++ b/src/version.c
@@ -747,6 +747,8 @@ static char *(features[]) =
 static int included_patches[] =
 {   /* Add new patch number below this line */
 /**/
+    882,
+/**/
     881,
 /**/
     880,