# HG changeset patch # User Bram Moolenaar # Date 1569942904 -7200 # Node ID 6c3a8312486d9e520d13202e36aee91b14baf9c9 # Parent 96632a3c3d90ac1f1f7dc78c19fe6e07bcaacb0d patch 8.1.2107: various memory leaks reported by asan Commit: https://github.com/vim/vim/commit/8617348e2110c2c8387ea448a6258f1effa8d249 Author: Bram Moolenaar Date: Tue Oct 1 17:02:16 2019 +0200 patch 8.1.2107: various memory leaks reported by asan Problem: Various memory leaks reported by asan. Solution: Free the memory. (Ozaki Kiichi, closes https://github.com/vim/vim/issues/5003) diff --git a/src/buffer.c b/src/buffer.c --- a/src/buffer.c +++ b/src/buffer.c @@ -880,6 +880,7 @@ free_buffer(buf_T *buf) /* b:changedtick uses an item in buf_T, remove it now */ dictitem_remove(buf->b_vars, (dictitem_T *)&buf->b_ct_di); unref_var_dict(buf->b_vars); + remove_listeners(buf); #endif #ifdef FEAT_LUA lua_buffer_free(buf); @@ -908,6 +909,7 @@ free_buffer(buf_T *buf) #ifdef FEAT_JOB_CHANNEL vim_free(buf->b_prompt_text); free_callback(&buf->b_prompt_callback); + free_callback(&buf->b_prompt_interrupt); #endif buf_hashtab_remove(buf); diff --git a/src/change.c b/src/change.c --- a/src/change.c +++ b/src/change.c @@ -300,7 +300,7 @@ f_listener_remove(typval_T *argvars, typ int id = tv_get_number(argvars); buf_T *buf; - for (buf = firstbuf; buf != NULL; buf = buf->b_next) + FOR_ALL_BUFFERS(buf) { prev = NULL; for (lnr = buf->b_listener; lnr != NULL; lnr = next) @@ -402,6 +402,24 @@ invoke_listeners(buf_T *buf) after_updating_screen(TRUE); recursive = FALSE; } + +/* + * Remove all listeners associated with "buf". + */ + void +remove_listeners(buf_T *buf) +{ + listener_T *lnr; + listener_T *next; + + for (lnr = buf->b_listener; lnr != NULL; lnr = next) + { + next = lnr->lr_next; + free_callback(&lnr->lr_callback); + vim_free(lnr); + } + buf->b_listener = NULL; +} #endif /* diff --git a/src/eval.c b/src/eval.c --- a/src/eval.c +++ b/src/eval.c @@ -2914,9 +2914,17 @@ eval_lambda( semsg(_(e_missingparen), "lambda"); } clear_tv(rettv); - return FAIL; + ret = FAIL; } - return call_func_rettv(arg, rettv, evaluate, NULL, &base); + else + ret = call_func_rettv(arg, rettv, evaluate, NULL, &base); + + // Clear the funcref afterwards, so that deleting it while + // evaluating the arguments is possible (see test55). + if (evaluate) + clear_tv(&base); + + return ret; } /* diff --git a/src/evalfunc.c b/src/evalfunc.c --- a/src/evalfunc.c +++ b/src/evalfunc.c @@ -2213,8 +2213,7 @@ f_expand(typval_T *argvars, typval_T *re { if (rettv_list_alloc(rettv) != FAIL && result != NULL) list_append_string(rettv->vval.v_list, result, -1); - else - vim_free(result); + vim_free(result); } else rettv->vval.v_string = result; diff --git a/src/option.c b/src/option.c --- a/src/option.c +++ b/src/option.c @@ -686,7 +686,7 @@ set_local_options_default(win_T *wp, int && (do_buffer || (p->indir & PV_BUF) == 0) && !(options[i].flags & P_NODEFAULT) && !optval_default(p, varp, FALSE)) - set_option_default(i, OPT_LOCAL, FALSE); + set_option_default(i, OPT_FREE|OPT_LOCAL, FALSE); } unblock_autocmds(); diff --git a/src/popupwin.c b/src/popupwin.c --- a/src/popupwin.c +++ b/src/popupwin.c @@ -3365,6 +3365,7 @@ update_popups(void (*win_update)(win_T * trunc_string(wp->w_popup_title, title, total_width - 2, len); screen_puts(title, wp->w_winrow, wp->w_wincol + 1, wp->w_popup_border[0] > 0 ? border_attr[0] : popup_attr); + vim_free(title); } // Compute scrollbar thumb position and size. diff --git a/src/proto/change.pro b/src/proto/change.pro --- a/src/proto/change.pro +++ b/src/proto/change.pro @@ -7,6 +7,7 @@ void f_listener_flush(typval_T *argvars, void f_listener_remove(typval_T *argvars, typval_T *rettv); void may_invoke_listeners(buf_T *buf, linenr_T lnum, linenr_T lnume, int added); void invoke_listeners(buf_T *buf); +void remove_listeners(buf_T *buf); void changed_bytes(linenr_T lnum, colnr_T col); void appended_lines(linenr_T lnum, long count); void appended_lines_mark(linenr_T lnum, long count); diff --git a/src/scriptfile.c b/src/scriptfile.c --- a/src/scriptfile.c +++ b/src/scriptfile.c @@ -1358,7 +1358,10 @@ free_scriptnames(void) int i; for (i = script_items.ga_len; i > 0; --i) + { vim_free(SCRIPT_ITEM(i).sn_name); + ga_clear(&SCRIPT_ITEM(i).sn_prl_ga); + } ga_clear(&script_items); } diff --git a/src/terminal.c b/src/terminal.c --- a/src/terminal.c +++ b/src/terminal.c @@ -4602,6 +4602,7 @@ read_dump_file(FILE *fd, VTermPos *curso } ga_clear(&ga_text); + ga_clear(&ga_cell); vim_free(prev_char); return max_cells; @@ -4733,7 +4734,7 @@ term_load_dump(typval_T *argvars, typval buf = curbuf; while (!(curbuf->b_ml.ml_flags & ML_EMPTY)) ml_delete((linenr_T)1, FALSE); - ga_clear(&curbuf->b_term->tl_scrollback); + free_scrollback(curbuf->b_term); redraw_later(NOT_VALID); } } diff --git a/src/testdir/test_method.vim b/src/testdir/test_method.vim --- a/src/testdir/test_method.vim +++ b/src/testdir/test_method.vim @@ -140,6 +140,10 @@ func Test_method_lambda() " todo: lambda accepts more arguments than it consumes " call assert_fails('eval "text"->{x -> x .. " extended"}("more")', 'E99:') + + let l = [1, 2, 3] + eval l->{x -> x}() + call assert_equal(1, test_refcount(l)) endfunc func Test_method_not_supported() diff --git a/src/version.c b/src/version.c --- a/src/version.c +++ b/src/version.c @@ -754,6 +754,8 @@ static char *(features[]) = static int included_patches[] = { /* Add new patch number below this line */ /**/ + 2107, +/**/ 2106, /**/ 2105,