Skip to content

Commit 67da21a

Browse files
committed
patch 8.2.2636: memory leak when compiling inline function
Problem: Memory leak when compiling inline function. Solution: Free the prefetched line.
1 parent 7a6eaa0 commit 67da21a

6 files changed

Lines changed: 26 additions & 9 deletions

File tree

src/eval.c

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2179,8 +2179,8 @@ clear_evalarg(evalarg_T *evalarg, exarg_T *eap)
21792179
evalarg->eval_tofree = NULL;
21802180
}
21812181

2182-
vim_free(evalarg->eval_tofree_lambda);
2183-
evalarg->eval_tofree_lambda = NULL;
2182+
VIM_CLEAR(evalarg->eval_tofree_cmdline);
2183+
VIM_CLEAR(evalarg->eval_tofree_lambda);
21842184
}
21852185
}
21862186

src/globals.h

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1898,7 +1898,8 @@ EXTERN listitem_T range_list_item;
18981898
// Passed to an eval() function to enable evaluation.
18991899
EXTERN evalarg_T EVALARG_EVALUATE
19001900
# ifdef DO_INIT
1901-
= {EVAL_EVALUATE, 0, NULL, NULL, NULL, {0, 0, 0, 0, NULL}, NULL, NULL}
1901+
= {EVAL_EVALUATE, 0, NULL, NULL, NULL, {0, 0, 0, 0, NULL},
1902+
NULL, NULL, NULL}
19021903
# endif
19031904
;
19041905
#endif

src/structs.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1882,6 +1882,9 @@ typedef struct {
18821882
// pointer to the last line obtained with getsourceline()
18831883
char_u *eval_tofree;
18841884

1885+
// pointer to the last line of an inline function
1886+
char_u *eval_tofree_cmdline;
1887+
18851888
// pointer to the lines concatenated for a lambda.
18861889
char_u *eval_tofree_lambda;
18871890
} evalarg_T;

src/userfunc.c

Lines changed: 7 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -970,17 +970,18 @@ lambda_function_body(
970970

971971
ga_init2(&newlines, (int)sizeof(char_u *), 10);
972972
if (get_function_body(&eap, &newlines, NULL, &line_to_free) == FAIL)
973+
{
974+
vim_free(cmdline);
973975
goto erret;
976+
}
974977
if (cmdline != NULL)
975978
{
976979
// Something comes after the "}".
977980
*arg = eap.nextcmd;
978-
if (evalarg->eval_cctx == NULL)
979-
{
980-
// Need to keep the line and free it/ later.
981-
vim_free(evalarg->eval_tofree_lambda);
982-
evalarg->eval_tofree_lambda = cmdline;
983-
}
981+
982+
// "arg" points into cmdline, need to keep the line and free it later.
983+
vim_free(evalarg->eval_tofree_cmdline);
984+
evalarg->eval_tofree_cmdline = cmdline;
984985
}
985986
else
986987
*arg = (char_u *)"";

src/version.c

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -750,6 +750,8 @@ static char *(features[]) =
750750

751751
static int included_patches[] =
752752
{ /* Add new patch number below this line */
753+
/**/
754+
2636,
753755
/**/
754756
2635,
755757
/**/

src/vim9compile.c

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3202,6 +3202,16 @@ compile_lambda(char_u **arg, cctx_T *cctx)
32023202
// Compile the function into instructions.
32033203
compile_def_function(ufunc, TRUE, PROFILING(ufunc), cctx);
32043204

3205+
// evalarg.eval_tofree_cmdline may have a copy of the last line and "*arg"
3206+
// points into it. Point to the original line to avoid a dangling pointer.
3207+
if (evalarg.eval_tofree_cmdline != NULL)
3208+
{
3209+
size_t off = *arg - evalarg.eval_tofree_cmdline;
3210+
3211+
*arg = ((char_u **)cctx->ctx_ufunc->uf_lines.ga_data)[cctx->ctx_lnum]
3212+
+ off;
3213+
}
3214+
32053215
clear_evalarg(&evalarg, NULL);
32063216

32073217
if (ufunc->uf_def_status == UF_COMPILED)

0 commit comments

Comments
 (0)