summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorBram Moolenaar <Bram@vim.org>2021-03-21 22:12:34 +0100
committerBram Moolenaar <Bram@vim.org>2021-03-21 22:12:34 +0100
commit67da21a14726b106b49744f9773eba132fedd5f2 (patch)
tree64c770c5e6b831fac7a5d230516fedd3512fb9b6
parent7a6eaa06f98cef61d2131c25b4b47b8262cb8f59 (diff)
patch 8.2.2636: memory leak when compiling inline functionv8.2.2636
Problem: Memory leak when compiling inline function. Solution: Free the prefetched line.
-rw-r--r--src/eval.c4
-rw-r--r--src/globals.h3
-rw-r--r--src/structs.h3
-rw-r--r--src/userfunc.c13
-rw-r--r--src/version.c2
-rw-r--r--src/vim9compile.c10
6 files changed, 26 insertions, 9 deletions
diff --git a/src/eval.c b/src/eval.c
index aa5f5b8243..6cdc10f68b 100644
--- a/src/eval.c
+++ b/src/eval.c
@@ -2179,8 +2179,8 @@ clear_evalarg(evalarg_T *evalarg, exarg_T *eap)
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);
}
}
diff --git a/src/globals.h b/src/globals.h
index cb3b4f4b76..94ec54b9aa 100644
--- 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
diff --git a/src/structs.h b/src/structs.h
index 0ca9203406..75ad127810 100644
--- 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;
diff --git a/src/userfunc.c b/src/userfunc.c
index 51894dc101..a53c4769c7 100644
--- 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 *)"";
diff --git a/src/version.c b/src/version.c
index cdce8cc767..bdc23a4005 100644
--- 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,
diff --git a/src/vim9compile.c b/src/vim9compile.c
index 09b1fce83b..535de057c6 100644
--- a/src/vim9compile.c
+++ b/src/vim9compile.c
@@ -3202,6 +3202,16 @@ compile_lambda(char_u **arg, cctx_T *cctx)
// 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)