summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorBram Moolenaar <Bram@vim.org>2017-06-25 20:57:18 +0200
committerBram Moolenaar <Bram@vim.org>2017-06-25 20:57:18 +0200
commit182a17b1e80b92826204d967808df0d30eb2ef27 (patch)
tree7410683c601c531585b1a072132ad19fa3ba1132
parent774e5a9673260b1b8b88463669213a96637f72e8 (diff)
patch 8.0.0676: crash when closing quickfix window in autocmdv8.0.0676
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.
-rw-r--r--runtime/doc/eval.txt13
-rw-r--r--src/evalfunc.c20
-rw-r--r--src/option.c78
-rw-r--r--src/version.c2
4 files changed, 80 insertions, 33 deletions
diff --git a/runtime/doc/eval.txt b/runtime/doc/eval.txt
index 6c5155022f..c17512a8a4 100644
--- a/runtime/doc/eval.txt
+++ b/runtime/doc/eval.txt
@@ -1,4 +1,4 @@
-*eval.txt* For Vim version 8.0. Last change: 2017 Jun 24
+*eval.txt* For Vim version 8.0. Last change: 2017 Jun 25
VIM REFERENCE MANUAL by Bram Moolenaar
@@ -7942,8 +7942,19 @@ test_override({name}, {val}) *test_override()*
name effect when {val} is non-zero ~
redraw disable the redrawing() function
char_avail disable the char_avail() function
+ starting reset the "starting" variable, see below
ALL clear all overrides ({val} is not used)
+ "starting" is to be used when a test should behave like
+ startup was done. Since the tests are run by sourcing a
+ script the "starting" variable is non-zero. This is usually a
+ good thing (tests run faster), but sometimes changes behavior
+ in a way that the test doesn't work properly.
+ When using: >
+ call test_override('starting', 1)
+< The value of "starting" is saved. It is restored by: >
+ call test_override('starting', 0)
+
test_settime({expr}) *test_settime()*
Set the time Vim uses internally. Currently only used for
timestamps in the history, as they are used in viminfo, and
diff --git a/src/evalfunc.c b/src/evalfunc.c
index ac232a3b3e..2d796f7e13 100644
--- a/src/evalfunc.c
+++ b/src/evalfunc.c
@@ -12398,6 +12398,7 @@ f_test_override(typval_T *argvars, typval_T *rettv UNUSED)
{
char_u *name = (char_u *)"";
int val;
+ static int save_starting = -1;
if (argvars[0].v_type != VAR_STRING
|| (argvars[1].v_type) != VAR_NUMBER)
@@ -12411,10 +12412,29 @@ f_test_override(typval_T *argvars, typval_T *rettv UNUSED)
disable_redraw_for_testing = val;
else if (STRCMP(name, (char_u *)"char_avail") == 0)
disable_char_avail_for_testing = val;
+ else if (STRCMP(name, (char_u *)"starting") == 0)
+ {
+ if (val)
+ {
+ if (save_starting < 0)
+ save_starting = starting;
+ starting = 0;
+ }
+ else
+ {
+ starting = save_starting;
+ save_starting = -1;
+ }
+ }
else if (STRCMP(name, (char_u *)"ALL") == 0)
{
disable_char_avail_for_testing = FALSE;
disable_redraw_for_testing = FALSE;
+ if (save_starting >= 0)
+ {
+ starting = save_starting;
+ save_starting = -1;
+ }
}
else
EMSG2(_(e_invarg2), name);
diff --git a/src/option.c b/src/option.c
index 154c28b5a8..8097a7f99b 100644
--- a/src/option.c
+++ b/src/option.c
@@ -4294,6 +4294,32 @@ set_title_defaults(void)
}
#endif
+#if defined(FEAT_AUTOCMD) && defined(FEAT_EVAL)
+ static void
+trigger_optionsset_string(
+ int opt_idx,
+ int opt_flags,
+ char_u *oldval,
+ char_u *newval)
+{
+ if (oldval != NULL && newval != NULL)
+ {
+ char_u buf_type[7];
+
+ sprintf((char *)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();
+ }
+ vim_free(oldval);
+ vim_free(newval);
+}
+#endif
+
/*
* Parse 'arg' for option settings.
*
@@ -4763,6 +4789,7 @@ do_set(
char_u *origval = NULL;
#if defined(FEAT_AUTOCMD) && defined(FEAT_EVAL)
char_u *saved_origval = NULL;
+ char_u *saved_newval = NULL;
#endif
unsigned newlen;
int comma;
@@ -5114,14 +5141,21 @@ do_set(
# ifdef FEAT_CRYPT
&& options[opt_idx].indir != PV_KEY
# endif
- && origval != NULL)
+ && origval != NULL && newval != NULL)
+ {
/* origval may be freed by
* did_set_string_option(), make a copy. */
saved_origval = vim_strsave(origval);
+ /* newval (and varp) may become invalid if the
+ * buffer is closed by autocommands. */
+ saved_newval = vim_strsave(newval);
+ }
#endif
/* Handle side effects, and set the global value for
- * ":set" on local options. */
+ * ":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);
@@ -5130,28 +5164,14 @@ do_set(
{
#if defined(FEAT_AUTOCMD) && defined(FEAT_EVAL)
vim_free(saved_origval);
+ vim_free(saved_newval);
#endif
goto skip;
}
#if defined(FEAT_AUTOCMD) && defined(FEAT_EVAL)
- if (saved_origval != NULL)
- {
- char_u buf_type[7];
-
- sprintf((char *)buf_type, "%s",
- (opt_flags & OPT_LOCAL) ? "local" : "global");
- set_vim_var_string(VV_OPTION_NEW,
- *(char_u **)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();
- vim_free(saved_origval);
- }
+ trigger_optionsset_string(opt_idx, opt_flags,
+ saved_origval, saved_newval);
#endif
-
}
else /* key code option */
{
@@ -5922,6 +5942,7 @@ set_string_option(
char_u *oldval;
#if defined(FEAT_AUTOCMD) && defined(FEAT_EVAL)
char_u *saved_oldval = NULL;
+ char_u *saved_newval = NULL;
#endif
char_u *r = NULL;
@@ -5945,26 +5966,19 @@ set_string_option(
&& options[opt_idx].indir != PV_KEY
# endif
)
+ {
saved_oldval = vim_strsave(oldval);
+ saved_newval = vim_strsave(s);
+ }
#endif
if ((r = did_set_string_option(opt_idx, varp, TRUE, oldval, NULL,
opt_flags)) == NULL)
did_set_option(opt_idx, opt_flags, TRUE);
- /* call autocommand after handling side effects */
#if defined(FEAT_AUTOCMD) && defined(FEAT_EVAL)
- if (saved_oldval != NULL)
- {
- char_u buf_type[7];
- sprintf((char *)buf_type, "%s",
- (opt_flags & OPT_LOCAL) ? "local" : "global");
- set_vim_var_string(VV_OPTION_NEW, *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();
- vim_free(saved_oldval);
- }
+ /* call autocommand after handling side effects */
+ trigger_optionsset_string(opt_idx, opt_flags,
+ saved_oldval, saved_newval);
#endif
}
return r;
diff --git a/src/version.c b/src/version.c
index 8dbd2a7d35..ab3185e0b2 100644
--- a/src/version.c
+++ b/src/version.c
@@ -765,6 +765,8 @@ static char *(features[]) =
static int included_patches[] =
{ /* Add new patch number below this line */
/**/
+ 676,
+/**/
675,
/**/
674,