Problem: Vim9: memory leak when using inline function.
Solution: Remember what strings to free.
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);
// leave room for "start"
if (ga_grow(gap, 1) == OK)
++gap->ga_len;
+ ga_init2(freegap, sizeof(char_u *), 10);
}
*start = *arg;
{
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;
}
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;
/*
* nested expression: (expression).
- * lambda: (arg) => expr
+ * or lambda: (arg) => expr
*/
case '(': ret = NOTDONE;
if (in_vim9script())
// 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;
{
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;
{
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
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
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)
static int included_patches[] =
{ /* Add new patch number below this line */
+/**/
+ 2866,
/**/
2865,
/**/