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:
12
src/eval.c
12
src/eval.c
@@ -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())
|
||||||
|
@@ -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;
|
||||||
|
@@ -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)
|
||||||
|
@@ -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,
|
||||||
/**/
|
/**/
|
||||||
|
Reference in New Issue
Block a user