0
0
mirror of https://github.com/vim/vim.git synced 2025-09-24 03:44:06 -04:00

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.
This commit is contained in:
Bram Moolenaar
2021-05-18 15:09:18 +02:00
parent d87c21a918
commit ecb664501d
4 changed files with 21 additions and 8 deletions

View File

@@ -416,6 +416,7 @@ skip_expr_concatenate(
int res; int res;
int vim9script = in_vim9script(); int vim9script = in_vim9script();
garray_T *gap = evalarg == NULL ? NULL : &evalarg->eval_ga; 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 save_flags = evalarg == NULL ? 0 : evalarg->eval_flags;
int evaluate = evalarg == NULL int evaluate = evalarg == NULL
? FALSE : (evalarg->eval_flags & EVAL_EVALUATE); ? FALSE : (evalarg->eval_flags & EVAL_EVALUATE);
@@ -427,6 +428,7 @@ skip_expr_concatenate(
// leave room for "start" // leave room for "start"
if (ga_grow(gap, 1) == OK) if (ga_grow(gap, 1) == OK)
++gap->ga_len; ++gap->ga_len;
ga_init2(freegap, sizeof(char_u *), 10);
} }
*start = *arg; *start = *arg;
@@ -444,7 +446,7 @@ skip_expr_concatenate(
{ {
if (evalarg->eval_ga.ga_len == 1) 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); ga_clear(gap);
gap->ga_itemsize = 0; gap->ga_itemsize = 0;
} }
@@ -471,7 +473,13 @@ skip_expr_concatenate(
ga_clear_strings(gap); ga_clear_strings(gap);
} }
else else
{
ga_clear(gap); ga_clear(gap);
// free lines that were explicitly marked for freeing
ga_clear_strings(freegap);
}
gap->ga_itemsize = 0; gap->ga_itemsize = 0;
if (p == NULL) if (p == NULL)
return FAIL; return FAIL;
@@ -3530,7 +3538,7 @@ eval7(
/* /*
* nested expression: (expression). * nested expression: (expression).
* lambda: (arg) => expr * or lambda: (arg) => expr
*/ */
case '(': ret = NOTDONE; case '(': ret = NOTDONE;
if (in_vim9script()) if (in_vim9script())

View File

@@ -1881,7 +1881,9 @@ typedef struct {
// Used to collect lines while parsing them, so that they can be // Used to collect lines while parsing them, so that they can be
// concatenated later. Used when "eval_ga.ga_itemsize" is not zero. // concatenated later. Used when "eval_ga.ga_itemsize" is not zero.
// "eval_ga.ga_data" is a list of pointers to lines. // "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_ga;
garray_T eval_freega;
// pointer to the last line obtained with getsourceline() // pointer to the last line obtained with getsourceline()
char_u *eval_tofree; char_u *eval_tofree;

View File

@@ -976,6 +976,7 @@ lambda_function_body(
{ {
int evaluate = (evalarg->eval_flags & EVAL_EVALUATE); int evaluate = (evalarg->eval_flags & EVAL_EVALUATE);
garray_T *gap = &evalarg->eval_ga; garray_T *gap = &evalarg->eval_ga;
garray_T *freegap = &evalarg->eval_freega;
ufunc_T *ufunc = NULL; ufunc_T *ufunc = NULL;
exarg_T eap; exarg_T eap;
garray_T newlines; garray_T newlines;
@@ -1026,7 +1027,7 @@ lambda_function_body(
{ {
char_u *p = skipwhite(((char_u **)newlines.ga_data)[idx]); 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; goto erret;
// Going to concatenate the lines after parsing. For an empty or // 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); pnl = vim_strnsave((char_u *)"\n", plen + 1);
if (pnl != NULL) if (pnl != NULL)
mch_memmove(pnl + 1, p, plen + 1); mch_memmove(pnl + 1, p, plen + 1);
((char_u **)gap->ga_data)[gap->ga_len] = pnl; ((char_u **)gap->ga_data)[gap->ga_len++] = pnl;
++gap->ga_len; ((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; goto erret;
if (cmdline != NULL) if (cmdline != NULL)
// more is following after the "}", which was skipped // more is following after the "}", which was skipped
@@ -1054,8 +1055,8 @@ lambda_function_body(
pnl = vim_strnsave((char_u *)"\n", plen + 1); pnl = vim_strnsave((char_u *)"\n", plen + 1);
if (pnl != NULL) if (pnl != NULL)
mch_memmove(pnl + 1, last, plen + 1); mch_memmove(pnl + 1, last, plen + 1);
((char_u **)gap->ga_data)[gap->ga_len] = pnl; ((char_u **)gap->ga_data)[gap->ga_len++] = pnl;
++gap->ga_len; ((char_u **)freegap->ga_data)[freegap->ga_len++] = pnl;
} }
if (cmdline != NULL) if (cmdline != NULL)

View File

@@ -750,6 +750,8 @@ static char *(features[]) =
static int included_patches[] = static int included_patches[] =
{ /* Add new patch number below this line */ { /* Add new patch number below this line */
/**/
2866,
/**/ /**/
2865, 2865,
/**/ /**/