diff options
author | Justin M. Keyes <justinkz@gmail.com> | 2018-02-02 02:04:36 +0100 |
---|---|---|
committer | Justin M. Keyes <justinkz@gmail.com> | 2018-02-11 15:27:57 +0100 |
commit | 2d151f7739a072ee7239cc44efec2b43c1b72679 (patch) | |
tree | f5ccd5402fcc1b5370c12a342c3980b859a1bb86 /src/nvim/option.c | |
parent | 61f9a7b0d0308228ce66b7848961152fbb65660f (diff) | |
download | rneovim-2d151f7739a072ee7239cc44efec2b43c1b72679.tar.gz rneovim-2d151f7739a072ee7239cc44efec2b43c1b72679.tar.bz2 rneovim-2d151f7739a072ee7239cc44efec2b43c1b72679.zip |
vim-patch:8.0.0676: crash when closing quickfix window in autocmd
Problem: Crash when closing the quickfix window in a FileType autocommand
that triggers when the quickfix window is opened.
Solution: Save the new value before triggering the OptionSet autocommand.
Add the "starting" flag to test_override() to make the text work.
https://github.com/vim/vim/commit/182a17b1e80b92826204d967808df0d30eb2ef27
Diffstat (limited to 'src/nvim/option.c')
-rw-r--r-- | src/nvim/option.c | 74 |
1 files changed, 37 insertions, 37 deletions
diff --git a/src/nvim/option.c b/src/nvim/option.c index aa1f5f3fe7..0858637a9d 100644 --- a/src/nvim/option.c +++ b/src/nvim/option.c @@ -1790,40 +1790,31 @@ do_set ( /* Set the new value. */ *(char_u **)(varp) = newval; - if (!starting && origval != NULL) { + if (!starting && origval != NULL && newval != NULL) { // origval may be freed by // did_set_string_option(), make a copy. saved_origval = xstrdup((char *) origval); + // newval (and varp) may become invalid if the + // buffer is closed by autocommands. + saved_newval = vim_strsave(newval); } - /* Handle side effects, and set the global value for - * ":set" on local options. */ + // Handle side effects, and set the global value for + // ":set" on local options. Note: when setting 'syntax' + // or 'filetype' autocommands may be triggered that can + // cause havoc. errmsg = did_set_string_option(opt_idx, (char_u **)varp, new_value_alloced, oldval, errbuf, opt_flags); // If error detected, print the error message. if (errmsg != NULL) { xfree(saved_origval); + xfree(saved_newval); goto skip; } - if (saved_origval != NULL) { - char buf_type[7]; - vim_snprintf(buf_type, ARRAY_SIZE(buf_type), "%s", - (opt_flags & OPT_LOCAL) ? "local" : "global"); - set_vim_var_string(VV_OPTION_NEW, *(char **) varp, -1); - set_vim_var_string(VV_OPTION_OLD, saved_origval, -1); - set_vim_var_string(VV_OPTION_TYPE, buf_type, -1); - apply_autocmds(EVENT_OPTIONSET, - (char_u *)options[opt_idx].fullname, - NULL, false, NULL); - reset_v_option_vars(); - xfree(saved_origval); - if (options[opt_idx].flags & P_UI_OPTION) { - ui_call_option_set(cstr_as_string(options[opt_idx].fullname), - STRING_OBJ(cstr_as_string(*(char **)varp))); - } - } + trigger_optionsset_string(opt_idx, opt_flags, saved_origval, + saved_newval); } else { // key code option(FIXME(tarruda): Show a warning or something // similar) @@ -2406,6 +2397,7 @@ static char *set_string_option(const int opt_idx, const char *const value, *varp = s; char *const saved_oldval = (starting ? NULL : xstrdup(oldval)); + char *const *saved_newval = (starting ? NULL : xstrdup(s)); char *const r = (char *)did_set_string_option( opt_idx, (char_u **)varp, (int)true, (char_u *)oldval, NULL, opt_flags); @@ -2414,23 +2406,8 @@ static char *set_string_option(const int opt_idx, const char *const value, } // call autocommand after handling side effects - if (saved_oldval != NULL) { - char buf_type[7]; - vim_snprintf(buf_type, ARRAY_SIZE(buf_type), "%s", - (opt_flags & OPT_LOCAL) ? "local" : "global"); - set_vim_var_string(VV_OPTION_NEW, (char *)(*varp), -1); - set_vim_var_string(VV_OPTION_OLD, saved_oldval, -1); - set_vim_var_string(VV_OPTION_TYPE, buf_type, -1); - apply_autocmds(EVENT_OPTIONSET, - (char_u *)options[opt_idx].fullname, - NULL, false, NULL); - reset_v_option_vars(); - xfree(saved_oldval); - if (options[opt_idx].flags & P_UI_OPTION) { - ui_call_option_set(cstr_as_string(options[opt_idx].fullname), - STRING_OBJ(cstr_as_string((char *)(*varp)))); - } - } + trigger_optionsset_string(opt_idx, opt_flags, + saved_oldval, saved_newval); return r; } @@ -4461,6 +4438,29 @@ static char *set_num_option(int opt_idx, char_u *varp, long value, return (char *)errmsg; } +static void trigger_optionsset_string(int opt_idx, int opt_flags, + char *oldval, char *newval) +{ + if (oldval != NULL && newval != NULL) { + char buf_type[7]; + + vim_snprintf(buf_type, ARRAY_SIZE(buf_type), "%s", + (opt_flags & OPT_LOCAL) ? "local" : "global"); + set_vim_var_string(VV_OPTION_OLD, oldval, -1); + set_vim_var_string(VV_OPTION_NEW, newval, -1); + set_vim_var_string(VV_OPTION_TYPE, buf_type, -1); + apply_autocmds(EVENT_OPTIONSET, + (char_u *)options[opt_idx].fullname, NULL, false, NULL); + reset_v_option_vars(); + if (options[opt_idx].flags & P_UI_OPTION) { + ui_call_option_set(cstr_as_string(options[opt_idx].fullname), + STRING_OBJ(cstr_as_string(newval))); + } + } + xfree(oldval); + xfree(newval); +} + /* * Called after an option changed: check if something needs to be redrawn. */ |