diff options
author | Bram Moolenaar <Bram@vim.org> | 2021-04-14 17:06:43 +0200 |
---|---|---|
committer | Bram Moolenaar <Bram@vim.org> | 2021-04-14 17:06:43 +0200 |
commit | b47bed2f7ada4dfae78f76f27473b83507e40315 (patch) | |
tree | 1ff4232659664ff3832adaaca98702a8e291f654 | |
parent | a3589a0d6cdb314e70421c0f2e5a2d1abf68e597 (diff) | |
download | vim-git-b47bed2f7ada4dfae78f76f27473b83507e40315.tar.gz |
patch 8.2.2764: memory leak when default function argument is allocatedv8.2.2764
Problem: Memory leak when default function argument is allocated.
Solution: Free the expression result.
-rw-r--r-- | src/testdir/test_functions.vim | 9 | ||||
-rw-r--r-- | src/userfunc.c | 9 | ||||
-rw-r--r-- | src/version.c | 2 |
3 files changed, 20 insertions, 0 deletions
diff --git a/src/testdir/test_functions.vim b/src/testdir/test_functions.vim index 8ee36794a..1cce8a0b1 100644 --- a/src/testdir/test_functions.vim +++ b/src/testdir/test_functions.vim @@ -1497,6 +1497,7 @@ endfunc func Test_balloon_show() CheckFeature balloon_eval + " This won't do anything but must not crash either. call balloon_show('hi!') if !has('gui_running') @@ -2650,4 +2651,12 @@ func Test_browsedir() call assert_fails('call browsedir("open", [])', 'E730:') endfunc +func HasDefault(msg = 'msg') + return a:msg +endfunc + +func Test_default_arg_value() + call assert_equal('msg', HasDefault()) +endfunc + " vim: shiftwidth=2 sts=2 expandtab diff --git a/src/userfunc.c b/src/userfunc.c index 772d45d12..99d4e0334 100644 --- a/src/userfunc.c +++ b/src/userfunc.c @@ -2188,6 +2188,8 @@ call_user_func( int islambda = FALSE; char_u numbuf[NUMBUFLEN]; char_u *name; + typval_T *tv_to_free[MAX_FUNC_ARGS]; + int tv_to_free_len = 0; #ifdef FEAT_PROFILE profinfo_T profile_info; #endif @@ -2333,6 +2335,7 @@ call_user_func( if (isdefault) { char_u *default_expr = NULL; + def_rettv.v_type = VAR_NUMBER; def_rettv.vval.v_number = -1; @@ -2374,6 +2377,10 @@ call_user_func( v->di_tv = isdefault ? def_rettv : argvars[i]; v->di_tv.v_lock = VAR_FIXED; + if (isdefault) + // Need to free this later, no matter where it's stored. + tv_to_free[tv_to_free_len++] = &v->di_tv; + if (addlocal) { // Named arguments should be accessed without the "a:" prefix in @@ -2563,6 +2570,8 @@ call_user_func( did_emsg |= save_did_emsg; funcdepth_decrement(); + for (i = 0; i < tv_to_free_len; ++i) + clear_tv(tv_to_free[i]); cleanup_function_call(fc); } diff --git a/src/version.c b/src/version.c index 3dee026c1..6ad07f7d7 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 */ /**/ + 2764, +/**/ 2763, /**/ 2762, |