changeset 24190:5f3a2d31c48d v8.2.2636

patch 8.2.2636: memory leak when compiling inline function Commit: https://github.com/vim/vim/commit/67da21a14726b106b49744f9773eba132fedd5f2 Author: Bram Moolenaar <Bram@vim.org> Date: Sun Mar 21 22:12:34 2021 +0100 patch 8.2.2636: memory leak when compiling inline function Problem: Memory leak when compiling inline function. Solution: Free the prefetched line.
author Bram Moolenaar <Bram@vim.org>
date Sun, 21 Mar 2021 22:15:03 +0100
parents 60c5b6cb5130
children a464593df512
files src/eval.c src/globals.h src/structs.h src/userfunc.c src/version.c src/vim9compile.c
diffstat 6 files changed, 26 insertions(+), 9 deletions(-) [+]
line wrap: on
line diff
--- a/src/eval.c
+++ b/src/eval.c
@@ -2179,8 +2179,8 @@ clear_evalarg(evalarg_T *evalarg, exarg_
 	    evalarg->eval_tofree = NULL;
 	}
 
-	vim_free(evalarg->eval_tofree_lambda);
-	evalarg->eval_tofree_lambda = NULL;
+	VIM_CLEAR(evalarg->eval_tofree_cmdline);
+	VIM_CLEAR(evalarg->eval_tofree_lambda);
     }
 }
 
--- a/src/globals.h
+++ b/src/globals.h
@@ -1898,7 +1898,8 @@ EXTERN listitem_T range_list_item;
 // Passed to an eval() function to enable evaluation.
 EXTERN evalarg_T EVALARG_EVALUATE
 # ifdef DO_INIT
-	= {EVAL_EVALUATE, 0, NULL, NULL, NULL, {0, 0, 0, 0, NULL}, NULL, NULL}
+	= {EVAL_EVALUATE, 0, NULL, NULL, NULL, {0, 0, 0, 0, NULL},
+							      NULL, NULL, NULL}
 # endif
 	;
 #endif
--- a/src/structs.h
+++ b/src/structs.h
@@ -1882,6 +1882,9 @@ typedef struct {
     // pointer to the last line obtained with getsourceline()
     char_u	*eval_tofree;
 
+    // pointer to the last line of an inline function
+    char_u	*eval_tofree_cmdline;
+
     // pointer to the lines concatenated for a lambda.
     char_u	*eval_tofree_lambda;
 } evalarg_T;
--- a/src/userfunc.c
+++ b/src/userfunc.c
@@ -970,17 +970,18 @@ lambda_function_body(
 
     ga_init2(&newlines, (int)sizeof(char_u *), 10);
     if (get_function_body(&eap, &newlines, NULL, &line_to_free) == FAIL)
+    {
+	vim_free(cmdline);
 	goto erret;
+    }
     if (cmdline != NULL)
     {
 	// Something comes after the "}".
 	*arg = eap.nextcmd;
-	if (evalarg->eval_cctx == NULL)
-	{
-	    // Need to keep the line and free it/ later.
-	    vim_free(evalarg->eval_tofree_lambda);
-	    evalarg->eval_tofree_lambda = cmdline;
-	}
+
+	// "arg" points into cmdline, need to keep the line and free it later.
+	vim_free(evalarg->eval_tofree_cmdline);
+	evalarg->eval_tofree_cmdline = cmdline;
     }
     else
 	*arg = (char_u *)"";
--- 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 */
 /**/
+    2636,
+/**/
     2635,
 /**/
     2634,
--- a/src/vim9compile.c
+++ b/src/vim9compile.c
@@ -3202,6 +3202,16 @@ compile_lambda(char_u **arg, cctx_T *cct
     // Compile the function into instructions.
     compile_def_function(ufunc, TRUE, PROFILING(ufunc), cctx);
 
+    // evalarg.eval_tofree_cmdline may have a copy of the last line and "*arg"
+    // points into it.  Point to the original line to avoid a dangling pointer.
+    if (evalarg.eval_tofree_cmdline != NULL)
+    {
+	size_t	off = *arg - evalarg.eval_tofree_cmdline;
+
+	*arg = ((char_u **)cctx->ctx_ufunc->uf_lines.ga_data)[cctx->ctx_lnum]
+									 + off;
+    }
+
     clear_evalarg(&evalarg, NULL);
 
     if (ufunc->uf_def_status == UF_COMPILED)