Mercurial > vim
diff src/vim9execute.c @ 23699:317018f62643 v8.2.2391
patch 8.2.2391: memory leak when creating a global function with closure
Commit: https://github.com/vim/vim/commit/0d3de8cb590aed90be71d96eb3dbc6addf80bb11
Author: Bram Moolenaar <Bram@vim.org>
Date: Fri Jan 22 20:46:27 2021 +0100
patch 8.2.2391: memory leak when creating a global function with closure
Problem: Memory leak when creating a global function with closure.
Solution: Create a separate partial for every instantiated function.
author | Bram Moolenaar <Bram@vim.org> |
---|---|
date | Fri, 22 Jan 2021 21:00:05 +0100 |
parents | 19073a768852 |
children | e3720756acdc |
line wrap: on
line diff
--- a/src/vim9execute.c +++ b/src/vim9execute.c @@ -263,7 +263,8 @@ call_dfunc(int cdf_idx, partial_T *pt, i } ectx->ec_stack.ga_len += STACK_FRAME_SIZE + varcount; - if (pt != NULL || ufunc->uf_partial != NULL || ufunc->uf_flags & FC_CLOSURE) + if (pt != NULL || ufunc->uf_partial != NULL + || (ufunc->uf_flags & FC_CLOSURE)) { outer_T *outer = ALLOC_CLEAR_ONE(outer_T); @@ -1062,7 +1063,7 @@ fill_partial_and_closure(partial_T *pt, pt->pt_func = ufunc; pt->pt_refcount = 1; - if (pt->pt_func->uf_flags & FC_CLOSURE) + if (ufunc->uf_flags & FC_CLOSURE) { dfunc_T *dfunc = ((dfunc_T *)def_functions.ga_data) + ectx->ec_dfunc_idx; @@ -1093,7 +1094,7 @@ fill_partial_and_closure(partial_T *pt, ++pt->pt_refcount; ++ectx->ec_funcrefs.ga_len; } - ++pt->pt_func->uf_refcount; + ++ufunc->uf_refcount; return OK; } @@ -1243,24 +1244,32 @@ call_def_function( ectx.ec_frame_idx = ectx.ec_stack.ga_len; initial_frame_idx = ectx.ec_frame_idx; - if (partial != NULL || ufunc->uf_partial != NULL) { - ectx.ec_outer = ALLOC_CLEAR_ONE(outer_T); - if (ectx.ec_outer == NULL) - goto failed_early; - if (partial != NULL) + dfunc_T *dfunc = ((dfunc_T *)def_functions.ga_data) + + ufunc->uf_dfunc_idx; + ufunc_T *base_ufunc = dfunc->df_ufunc; + + // "uf_partial" is on the ufunc that "df_ufunc" points to, as is done + // by copy_func(). + if (partial != NULL || base_ufunc->uf_partial != NULL) { - if (partial->pt_outer.out_stack == NULL && current_ectx != NULL) + ectx.ec_outer = ALLOC_CLEAR_ONE(outer_T); + if (ectx.ec_outer == NULL) + goto failed_early; + if (partial != NULL) { - if (current_ectx->ec_outer != NULL) - *ectx.ec_outer = *current_ectx->ec_outer; + if (partial->pt_outer.out_stack == NULL && current_ectx != NULL) + { + if (current_ectx->ec_outer != NULL) + *ectx.ec_outer = *current_ectx->ec_outer; + } + else + *ectx.ec_outer = partial->pt_outer; } else - *ectx.ec_outer = partial->pt_outer; + *ectx.ec_outer = base_ufunc->uf_partial->pt_outer; + ectx.ec_outer->out_up_is_copy = TRUE; } - else - *ectx.ec_outer = ufunc->uf_partial->pt_outer; - ectx.ec_outer->out_up_is_copy = TRUE; } // dummy frame entries