Mercurial > vim
changeset 24448:faac16c365b6 v8.2.2764
patch 8.2.2764: memory leak when default function argument is allocated
Commit: https://github.com/vim/vim/commit/b47bed2f7ada4dfae78f76f27473b83507e40315
Author: Bram Moolenaar <Bram@vim.org>
Date: Wed Apr 14 17:06:43 2021 +0200
patch 8.2.2764: memory leak when default function argument is allocated
Problem: Memory leak when default function argument is allocated.
Solution: Free the expression result.
author | Bram Moolenaar <Bram@vim.org> |
---|---|
date | Wed, 14 Apr 2021 17:15:05 +0200 |
parents | bbe84a902d14 |
children | ca0d84e008e5 |
files | src/testdir/test_functions.vim src/userfunc.c src/version.c |
diffstat | 3 files changed, 20 insertions(+), 0 deletions(-) [+] |
line wrap: on
line diff
--- 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
--- 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); }