From 63b1a7d0cf6d192585c4929cff188e9c255c0a76 Mon Sep 17 00:00:00 2001 From: Jan Edmund Lazo Date: Sat, 29 Sep 2018 00:41:02 -0400 Subject: [PATCH 1/6] vim-patch:8.0.1485: weird autocmd may cause arglist to be changed recursively Problem: Weird autocmd may cause arglist to be changed recursively. Solution: Prevent recursively changing the argument list. (Christian Brabandt, closes vim/vim#2472) https://github.com/vim/vim/commit/9e33efd1523b85a70533930dd43a26925a2b648c --- src/nvim/ex_docmd.c | 9 +++++++++ src/nvim/globals.h | 2 ++ 2 files changed, 11 insertions(+) diff --git a/src/nvim/ex_docmd.c b/src/nvim/ex_docmd.c index ad51de46ee..cec5431bbd 100644 --- a/src/nvim/ex_docmd.c +++ b/src/nvim/ex_docmd.c @@ -6536,6 +6536,13 @@ void alist_expand(int *fnum_list, int fnum_len) void alist_set(alist_T *al, int count, char_u **files, int use_curbuf, int *fnum_list, int fnum_len) { int i; + static int recursive = 0; + + if (recursive) { + EMSG(_(e_au_recursive)); + return; + } + recursive++; alist_clear(al); ga_grow(&al->al_ga, count); @@ -6562,6 +6569,8 @@ void alist_set(alist_T *al, int count, char_u **files, int use_curbuf, int *fnum if (al == &global_alist) arg_had_last = FALSE; + + recursive--; } /* diff --git a/src/nvim/globals.h b/src/nvim/globals.h index 9bba2379cd..5606747ce9 100644 --- a/src/nvim/globals.h +++ b/src/nvim/globals.h @@ -1099,6 +1099,8 @@ EXTERN char_u e_notset[] INIT(= N_("E764: Option '%s' is not set")); EXTERN char_u e_invalidreg[] INIT(= N_("E850: Invalid register name")); EXTERN char_u e_dirnotf[] INIT(= N_( "E919: Directory not found in '%s': \"%s\"")); +EXTERN char_u e_au_recursive[] INIT(= N_( + "E952: Autocommand caused recursive behavior")); EXTERN char_u e_unsupportedoption[] INIT(= N_("E519: Option not supported")); EXTERN char_u e_fnametoolong[] INIT(= N_("E856: Filename too long")); EXTERN char_u e_float_as_string[] INIT(= N_("E806: using Float as a String")); From 458a6f58b67298ad3df276ffcc525eb3b32b8a56 Mon Sep 17 00:00:00 2001 From: Jan Edmund Lazo Date: Sat, 29 Sep 2018 16:53:55 -0400 Subject: [PATCH 2/6] globals: arg_had_last is bool --- src/nvim/buffer.c | 2 +- src/nvim/ex_docmd.c | 2 +- src/nvim/globals.h | 2 +- src/nvim/main.c | 2 +- 4 files changed, 4 insertions(+), 4 deletions(-) diff --git a/src/nvim/buffer.c b/src/nvim/buffer.c index a28d9774ab..5ad56ff450 100644 --- a/src/nvim/buffer.c +++ b/src/nvim/buffer.c @@ -4535,7 +4535,7 @@ do_arg_all ( for (i = 0; i < count && i < opened_len && !got_int; ++i) { if (alist == &global_alist && i == global_alist.al_ga.ga_len - 1) - arg_had_last = TRUE; + arg_had_last = true; if (opened[i] > 0) { /* Move the already present window to below the current window */ if (curwin->w_arg_idx != i) { diff --git a/src/nvim/ex_docmd.c b/src/nvim/ex_docmd.c index cec5431bbd..bb23734a7c 100644 --- a/src/nvim/ex_docmd.c +++ b/src/nvim/ex_docmd.c @@ -6568,7 +6568,7 @@ void alist_set(alist_T *al, int count, char_u **files, int use_curbuf, int *fnum } if (al == &global_alist) - arg_had_last = FALSE; + arg_had_last = false; recursive--; } diff --git a/src/nvim/globals.h b/src/nvim/globals.h index 5606747ce9..3af5040275 100644 --- a/src/nvim/globals.h +++ b/src/nvim/globals.h @@ -528,7 +528,7 @@ EXTERN buf_T *curbuf INIT(= NULL); // currently active buffer */ EXTERN alist_T global_alist; /* global argument list */ EXTERN int max_alist_id INIT(= 0); ///< the previous argument list id -EXTERN int arg_had_last INIT(= FALSE); /* accessed last file in +EXTERN bool arg_had_last INIT(= false); /* accessed last file in global_alist */ EXTERN int ru_col; /* column for ruler */ diff --git a/src/nvim/main.c b/src/nvim/main.c index 4b838a837c..c32fb351ef 100644 --- a/src/nvim/main.c +++ b/src/nvim/main.c @@ -1625,7 +1625,7 @@ static void edit_buffers(mparm_T *parmp, char_u *cwd) advance = false; } if (arg_idx == GARGCOUNT - 1) - arg_had_last = TRUE; + arg_had_last = true; ++arg_idx; } os_breakcheck(); From cf7e351c24349c0351e19fbd4533f715d00bf87c Mon Sep 17 00:00:00 2001 From: Jan Edmund Lazo Date: Sat, 29 Sep 2018 22:11:50 -0400 Subject: [PATCH 3/6] lint --- src/nvim/buffer.c | 5 +++-- src/nvim/ex_docmd.c | 4 ++-- src/nvim/globals.h | 4 ++-- src/nvim/main.c | 5 +++-- 4 files changed, 10 insertions(+), 8 deletions(-) diff --git a/src/nvim/buffer.c b/src/nvim/buffer.c index 5ad56ff450..68f6ff303b 100644 --- a/src/nvim/buffer.c +++ b/src/nvim/buffer.c @@ -4533,9 +4533,10 @@ do_arg_all ( use_firstwin = true; } - for (i = 0; i < count && i < opened_len && !got_int; ++i) { - if (alist == &global_alist && i == global_alist.al_ga.ga_len - 1) + for (i = 0; i < count && i < opened_len && !got_int; i++) { + if (alist == &global_alist && i == global_alist.al_ga.ga_len - 1) { arg_had_last = true; + } if (opened[i] > 0) { /* Move the already present window to below the current window */ if (curwin->w_arg_idx != i) { diff --git a/src/nvim/ex_docmd.c b/src/nvim/ex_docmd.c index bb23734a7c..f8d4e7d980 100644 --- a/src/nvim/ex_docmd.c +++ b/src/nvim/ex_docmd.c @@ -6567,9 +6567,9 @@ void alist_set(alist_T *al, int count, char_u **files, int use_curbuf, int *fnum xfree(files); } - if (al == &global_alist) + if (al == &global_alist) { arg_had_last = false; - + } recursive--; } diff --git a/src/nvim/globals.h b/src/nvim/globals.h index 3af5040275..2dc8073b1e 100644 --- a/src/nvim/globals.h +++ b/src/nvim/globals.h @@ -528,8 +528,8 @@ EXTERN buf_T *curbuf INIT(= NULL); // currently active buffer */ EXTERN alist_T global_alist; /* global argument list */ EXTERN int max_alist_id INIT(= 0); ///< the previous argument list id -EXTERN bool arg_had_last INIT(= false); /* accessed last file in - global_alist */ +EXTERN bool arg_had_last INIT(= false); // accessed last file in + // global_alist EXTERN int ru_col; /* column for ruler */ EXTERN int ru_wid; /* 'rulerfmt' width of ruler when non-zero */ diff --git a/src/nvim/main.c b/src/nvim/main.c index c32fb351ef..371c8d824e 100644 --- a/src/nvim/main.c +++ b/src/nvim/main.c @@ -1624,9 +1624,10 @@ static void edit_buffers(mparm_T *parmp, char_u *cwd) win_close(curwin, true); advance = false; } - if (arg_idx == GARGCOUNT - 1) + if (arg_idx == GARGCOUNT - 1) { arg_had_last = true; - ++arg_idx; + } + arg_idx++; } os_breakcheck(); if (got_int) { From 33ef9598145d5273234d6e7443d55d6f6ac0fa1e Mon Sep 17 00:00:00 2001 From: Jan Edmund Lazo Date: Sun, 30 Sep 2018 01:56:39 -0400 Subject: [PATCH 4/6] vim-patch:8.1.0068: nasty autocommands can still cause using freed memory Problem: Nasty autocommands can still cause using freed memory. Solution: Disallow using setloclist() and setqflist() recursively. https://github.com/vim/vim/commit/2f82ca7d79148ae931bf28a747ede06ba8a65de8 --- src/nvim/eval.c | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/src/nvim/eval.c b/src/nvim/eval.c index 44560792f0..41a9eeeb40 100644 --- a/src/nvim/eval.c +++ b/src/nvim/eval.c @@ -14664,6 +14664,7 @@ static void set_qf_ll_list(win_T *wp, typval_T *args, typval_T *rettv) static char *e_invact = N_("E927: Invalid action: '%s'"); const char *title = NULL; int action = ' '; + static int recursive = 0; rettv->vval.v_number = -1; dict_T *d = NULL; @@ -14671,6 +14672,9 @@ static void set_qf_ll_list(win_T *wp, typval_T *args, typval_T *rettv) if (list_arg->v_type != VAR_LIST) { EMSG(_(e_listreq)); return; + } else if (recursive != 0) { + EMSG(_(e_au_recursive)); + return; } typval_T *action_arg = &args[1]; @@ -14712,10 +14716,12 @@ skip_args: title = (wp ? "setloclist()" : "setqflist()"); } + recursive++; list_T *const l = list_arg->vval.v_list; if (set_errorlist(wp, l, action, (char_u *)title, d) == OK) { rettv->vval.v_number = 0; } + recursive--; } /* From 6a680548ec3e81e9d228cb8ac9e4380368068387 Mon Sep 17 00:00:00 2001 From: Jan Edmund Lazo Date: Sun, 30 Sep 2018 02:37:31 -0400 Subject: [PATCH 5/6] vim-patch:8.1.0066: nasty autocommand causes using freed memory Problem: Nasty autocommand causes using freed memory. (Dominique Pelle) Solution: Do not force executing autocommands if the value of 'syntax' or 'filetype' did not change. https://github.com/vim/vim/commit/c3ffc9b8d3015dc5280b297b4e3deb4f34944bd4 --- src/nvim/option.c | 18 +++++++++++++----- 1 file changed, 13 insertions(+), 5 deletions(-) diff --git a/src/nvim/option.c b/src/nvim/option.c index b4ee89d128..1440180e4b 100644 --- a/src/nvim/option.c +++ b/src/nvim/option.c @@ -2434,7 +2434,7 @@ did_set_string_option ( int did_chartab = FALSE; char_u **gvarp; bool free_oldval = (options[opt_idx].flags & P_ALLOCED); - int ft_changed = false; + bool value_changed = false; /* Get the global option to compare with, otherwise we would have to check * two values for all local options. */ @@ -3155,11 +3155,13 @@ did_set_string_option ( if (!valid_filetype(*varp)) { errmsg = e_invarg; } else { - ft_changed = STRCMP(oldval, *varp) != 0; + value_changed = STRCMP(oldval, *varp) != 0; } } else if (gvarp == &p_syn) { if (!valid_filetype(*varp)) { errmsg = e_invarg; + } else { + value_changed = STRCMP(oldval, *varp) != 0; } } else if (varp == &curwin->w_p_winhl) { if (!parse_winhl_opt(curwin)) { @@ -3235,14 +3237,20 @@ did_set_string_option ( */ /* When 'syntax' is set, load the syntax of that name */ if (varp == &(curbuf->b_p_syn)) { + // Only pass true for "force" when the value changed, to avoid + // endless recurrence. apply_autocmds(EVENT_SYNTAX, curbuf->b_p_syn, - curbuf->b_fname, TRUE, curbuf); + curbuf->b_fname, value_changed, curbuf); } else if (varp == &(curbuf->b_p_ft)) { // 'filetype' is set, trigger the FileType autocommand - if (!(opt_flags & OPT_MODELINE) || ft_changed) { + // Skip this when called from a modeline and the filetype was + // already set to this value. + // Only pass true for "force" when the value changed, to avoid + // endless recurrence. + if (!(opt_flags & OPT_MODELINE) || value_changed) { did_filetype = true; apply_autocmds(EVENT_FILETYPE, curbuf->b_p_ft, - curbuf->b_fname, true, curbuf); + curbuf->b_fname, value_changed, curbuf); // Just in case the old "curbuf" is now invalid if (varp != &(curbuf->b_p_ft)) { varp = NULL; From 9dcd5bd9c5272e28f7f52f579b74381e46ce827d Mon Sep 17 00:00:00 2001 From: Jan Edmund Lazo Date: Sun, 30 Sep 2018 02:53:18 -0400 Subject: [PATCH 6/6] vim-patch:8.1.0067: syntax highlighting not working when re-entering a buffer Problem: Syntax highlighting not working when re-entering a buffer. Solution: Do force executing autocommands when not called recursively. https://github.com/vim/vim/commit/a5616b0136cea2104a475d143a1685d71e9b2d3d --- src/nvim/option.c | 24 ++++++++++++++++-------- 1 file changed, 16 insertions(+), 8 deletions(-) diff --git a/src/nvim/option.c b/src/nvim/option.c index 1440180e4b..eb2780ce7a 100644 --- a/src/nvim/option.c +++ b/src/nvim/option.c @@ -3237,20 +3237,28 @@ did_set_string_option ( */ /* When 'syntax' is set, load the syntax of that name */ if (varp == &(curbuf->b_p_syn)) { - // Only pass true for "force" when the value changed, to avoid - // endless recurrence. - apply_autocmds(EVENT_SYNTAX, curbuf->b_p_syn, - curbuf->b_fname, value_changed, curbuf); + static int syn_recursive = 0; + + syn_recursive++; + // Only pass true for "force" when the value changed or not used + // recursively, to avoid endless recurrence. + apply_autocmds(EVENT_SYNTAX, curbuf->b_p_syn, curbuf->b_fname, + value_changed || syn_recursive == 1, curbuf); + syn_recursive--; } else if (varp == &(curbuf->b_p_ft)) { // 'filetype' is set, trigger the FileType autocommand // Skip this when called from a modeline and the filetype was // already set to this value. - // Only pass true for "force" when the value changed, to avoid - // endless recurrence. if (!(opt_flags & OPT_MODELINE) || value_changed) { + static int ft_recursive = 0; + + ft_recursive++; did_filetype = true; - apply_autocmds(EVENT_FILETYPE, curbuf->b_p_ft, - curbuf->b_fname, value_changed, curbuf); + // Only pass true for "force" when the value changed or not + // used recursively, to avoid endless recurrence. + apply_autocmds(EVENT_FILETYPE, curbuf->b_p_ft, curbuf->b_fname, + value_changed || ft_recursive == 1, curbuf); + ft_recursive--; // Just in case the old "curbuf" is now invalid if (varp != &(curbuf->b_p_ft)) { varp = NULL;