changeset 24655:3876d9629ebd v8.2.2866

patch 8.2.2866: Vim9: memory leak when using inline function Commit: https://github.com/vim/vim/commit/ecb664501d3b04d124fca69029b275c520401d40 Author: Bram Moolenaar <Bram@vim.org> Date: Tue May 18 15:09:18 2021 +0200 patch 8.2.2866: Vim9: memory leak when using inline function Problem: Vim9: memory leak when using inline function. Solution: Remember what strings to free.
author Bram Moolenaar <Bram@vim.org>
date Tue, 18 May 2021 15:15:02 +0200
parents f28527b7c2d3
children 7054589796e5
files src/eval.c src/structs.h src/userfunc.c src/version.c
diffstat 4 files changed, 21 insertions(+), 8 deletions(-) [+]
line wrap: on
line diff
--- a/src/eval.c
+++ b/src/eval.c
@@ -416,6 +416,7 @@ skip_expr_concatenate(
     int		res;
     int		vim9script = in_vim9script();
     garray_T    *gap = evalarg == NULL ? NULL : &evalarg->eval_ga;
+    garray_T    *freegap = evalarg == NULL ? NULL : &evalarg->eval_freega;
     int		save_flags = evalarg == NULL ? 0 : evalarg->eval_flags;
     int		evaluate = evalarg == NULL
 			       ? FALSE : (evalarg->eval_flags & EVAL_EVALUATE);
@@ -427,6 +428,7 @@ skip_expr_concatenate(
 	// leave room for "start"
 	if (ga_grow(gap, 1) == OK)
 	    ++gap->ga_len;
+	ga_init2(freegap, sizeof(char_u *), 10);
     }
     *start = *arg;
 
@@ -444,7 +446,7 @@ skip_expr_concatenate(
     {
 	if (evalarg->eval_ga.ga_len == 1)
 	{
-	    // just one line, no need to concatenate
+	    // just the one line, no need to concatenate
 	    ga_clear(gap);
 	    gap->ga_itemsize = 0;
 	}
@@ -471,7 +473,13 @@ skip_expr_concatenate(
 		ga_clear_strings(gap);
 	    }
 	    else
+	    {
 		ga_clear(gap);
+
+		// free lines that were explicitly marked for freeing
+		ga_clear_strings(freegap);
+	    }
+
 	    gap->ga_itemsize = 0;
 	    if (p == NULL)
 		return FAIL;
@@ -3530,7 +3538,7 @@ eval7(
 
     /*
      * nested expression: (expression).
-     * lambda: (arg) => expr
+     * or lambda: (arg) => expr
      */
     case '(':	ret = NOTDONE;
 		if (in_vim9script())
--- a/src/structs.h
+++ b/src/structs.h
@@ -1881,7 +1881,9 @@ typedef struct {
     // Used to collect lines while parsing them, so that they can be
     // concatenated later.  Used when "eval_ga.ga_itemsize" is not zero.
     // "eval_ga.ga_data" is a list of pointers to lines.
+    // "eval_freega" list pointers that need to be freed after concatenating.
     garray_T	eval_ga;
+    garray_T	eval_freega;
 
     // pointer to the last line obtained with getsourceline()
     char_u	*eval_tofree;
--- a/src/userfunc.c
+++ b/src/userfunc.c
@@ -976,6 +976,7 @@ lambda_function_body(
 {
     int		evaluate = (evalarg->eval_flags & EVAL_EVALUATE);
     garray_T	*gap = &evalarg->eval_ga;
+    garray_T	*freegap = &evalarg->eval_freega;
     ufunc_T	*ufunc = NULL;
     exarg_T	eap;
     garray_T	newlines;
@@ -1026,7 +1027,7 @@ lambda_function_body(
 	{
 	    char_u  *p = skipwhite(((char_u **)newlines.ga_data)[idx]);
 
-	    if (ga_grow(gap, 1) == FAIL)
+	    if (ga_grow(gap, 1) == FAIL || ga_grow(freegap, 1) == FAIL)
 		goto erret;
 
 	    // Going to concatenate the lines after parsing.  For an empty or
@@ -1039,10 +1040,10 @@ lambda_function_body(
 	    pnl = vim_strnsave((char_u *)"\n", plen + 1);
 	    if (pnl != NULL)
 		mch_memmove(pnl + 1, p, plen + 1);
-	    ((char_u **)gap->ga_data)[gap->ga_len] = pnl;
-	    ++gap->ga_len;
+	    ((char_u **)gap->ga_data)[gap->ga_len++] = pnl;
+	    ((char_u **)freegap->ga_data)[freegap->ga_len++] = pnl;
 	}
-	if (ga_grow(gap, 1) == FAIL)
+	if (ga_grow(gap, 1) == FAIL || ga_grow(freegap, 1) == FAIL)
 	    goto erret;
 	if (cmdline != NULL)
 	    // more is following after the "}", which was skipped
@@ -1054,8 +1055,8 @@ lambda_function_body(
 	pnl = vim_strnsave((char_u *)"\n", plen + 1);
 	if (pnl != NULL)
 	    mch_memmove(pnl + 1, last, plen + 1);
-	((char_u **)gap->ga_data)[gap->ga_len] = pnl;
-	++gap->ga_len;
+	((char_u **)gap->ga_data)[gap->ga_len++] = pnl;
+	((char_u **)freegap->ga_data)[freegap->ga_len++] = pnl;
     }
 
     if (cmdline != NULL)
--- a/src/version.c
+++ b/src/version.c
@@ -751,6 +751,8 @@ static char *(features[]) =
 static int included_patches[] =
 {   /* Add new patch number below this line */
 /**/
+    2866,
+/**/
     2865,
 /**/
     2864,