changeset 18225:6c3a8312486d v8.1.2107

patch 8.1.2107: various memory leaks reported by asan Commit: https://github.com/vim/vim/commit/8617348e2110c2c8387ea448a6258f1effa8d249 Author: Bram Moolenaar <Bram@vim.org> 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)
author Bram Moolenaar <Bram@vim.org>
date Tue, 01 Oct 2019 17:15:04 +0200
parents 96632a3c3d90
children 78e84b457783
files src/buffer.c src/change.c src/eval.c src/evalfunc.c src/option.c src/popupwin.c src/proto/change.pro src/scriptfile.c src/terminal.c src/testdir/test_method.vim src/version.c
diffstat 11 files changed, 46 insertions(+), 7 deletions(-) [+]
line wrap: on
line diff
--- 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);
--- 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
 
 /*
--- 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;
 }
 
 /*
--- 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;
--- 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();
--- 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.
--- 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);
--- 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);
 }
 
--- 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);
 	}
     }
--- 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()
--- 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,