diff options
author | Bram Moolenaar <Bram@vim.org> | 2021-05-18 15:09:18 +0200 |
---|---|---|
committer | Bram Moolenaar <Bram@vim.org> | 2021-05-18 15:09:18 +0200 |
commit | ecb664501d3b04d124fca69029b275c520401d40 (patch) | |
tree | d5cd0eb0140b636d75519b0156be5bafe3c92cb7 | |
parent | d87c21a918d8d611750f22d68fc638bf7a79b1d5 (diff) | |
download | vim-git-ecb664501d3b04d124fca69029b275c520401d40.tar.gz |
patch 8.2.2866: Vim9: memory leak when using inline functionv8.2.2866
Problem: Vim9: memory leak when using inline function.
Solution: Remember what strings to free.
-rw-r--r-- | src/eval.c | 12 | ||||
-rw-r--r-- | src/structs.h | 2 | ||||
-rw-r--r-- | src/userfunc.c | 13 | ||||
-rw-r--r-- | src/version.c | 2 |
4 files changed, 21 insertions, 8 deletions
diff --git a/src/eval.c b/src/eval.c index 97c5f78df..b5820b8d3 100644 --- a/src/eval.c +++ b/src/eval.c @@ -416,6 +416,7 @@ skip_expr_concatenate( 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); @@ -427,6 +428,7 @@ skip_expr_concatenate( // leave room for "start" if (ga_grow(gap, 1) == OK) ++gap->ga_len; + ga_init2(freegap, sizeof(char_u *), 10); } *start = *arg; @@ -444,7 +446,7 @@ skip_expr_concatenate( { 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; } @@ -471,7 +473,13 @@ skip_expr_concatenate( 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; @@ -3530,7 +3538,7 @@ eval7( /* * nested expression: (expression). - * lambda: (arg) => expr + * or lambda: (arg) => expr */ case '(': ret = NOTDONE; if (in_vim9script()) diff --git a/src/structs.h b/src/structs.h index 9861bb601..3bb641be8 100644 --- a/src/structs.h +++ b/src/structs.h @@ -1881,7 +1881,9 @@ typedef struct { // 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; diff --git a/src/userfunc.c b/src/userfunc.c index bc7d92384..dd6939c9a 100644 --- a/src/userfunc.c +++ b/src/userfunc.c @@ -976,6 +976,7 @@ lambda_function_body( { 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; @@ -1026,7 +1027,7 @@ lambda_function_body( { 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 @@ -1039,10 +1040,10 @@ lambda_function_body( 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 @@ -1054,8 +1055,8 @@ lambda_function_body( 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) diff --git a/src/version.c b/src/version.c index 5e2a52c1a..88dd5d6d9 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 */ /**/ + 2866, +/**/ 2865, /**/ 2864, |