From c202e4a86856594a6602a795314a081c497c2df5 Mon Sep 17 00:00:00 2001 From: Jan Edmund Lazo Date: Sat, 23 Mar 2019 00:58:00 -0400 Subject: [PATCH 01/19] vim-patch:8.1.0177: defining function in sandbox is inconsistent Problem: Defining function in sandbox is inconsistent, cannot use :function but can define a lambda. Solution: Allow defining a function in the sandbox, but also use the sandbox when executing it. (closes vim/vim#3182) https://github.com/vim/vim/commit/93343725b5fa1cf580a24302455980faacae8ee2 --- src/nvim/eval.c | 19 ++++++++++++++++++- src/nvim/ex_cmds.lua | 2 +- 2 files changed, 19 insertions(+), 2 deletions(-) diff --git a/src/nvim/eval.c b/src/nvim/eval.c index 5191328b5d..9163673a32 100644 --- a/src/nvim/eval.c +++ b/src/nvim/eval.c @@ -241,13 +241,14 @@ typedef enum { ///< the value (prevents error message). } GetLvalFlags; -// function flags +// flags used in uf_flags #define FC_ABORT 0x01 // abort function on error #define FC_RANGE 0x02 // function accepts range #define FC_DICT 0x04 // Dict function, uses "self" #define FC_CLOSURE 0x08 // closure, uses outer scope variables #define FC_DELETED 0x10 // :delfunction used while uf_refcount > 0 #define FC_REMOVED 0x20 // function redefined while uf_refcount > 0 +#define FC_SANDBOX 0x40 // function defined in the sandbox // The names of packages that once were loaded are remembered. static garray_T ga_loaded = { 0, 0, sizeof(char_u *), 4, NULL }; @@ -5853,6 +5854,9 @@ static int get_lambda_tv(char_u **arg, typval_T *rettv, bool evaluate) if (prof_def_func()) { func_do_profile(fp); } + if (sandbox) { + flags |= FC_SANDBOX; + } fp->uf_varargs = true; fp->uf_flags = flags; fp->uf_calls = 0; @@ -20315,6 +20319,9 @@ void ex_function(exarg_T *eap) if (prof_def_func()) func_do_profile(fp); fp->uf_varargs = varargs; + if (sandbox) { + flags |= FC_SANDBOX; + } fp->uf_flags = flags; fp->uf_calls = 0; fp->uf_script_ID = current_SID; @@ -21305,6 +21312,7 @@ void call_user_func(ufunc_T *fp, int argcount, typval_T *argvars, char_u *save_sourcing_name; linenr_T save_sourcing_lnum; scid_T save_current_SID; + bool using_sandbox = false; funccall_T *fc; int save_did_emsg; static int depth = 0; @@ -21462,6 +21470,12 @@ void call_user_func(ufunc_T *fp, int argcount, typval_T *argvars, save_sourcing_name = sourcing_name; save_sourcing_lnum = sourcing_lnum; sourcing_lnum = 1; + + if (fp->uf_flags & FC_SANDBOX) { + using_sandbox = true; + sandbox++; + } + // need space for new sourcing_name: // * save_sourcing_name // * "["number"].." or "function " @@ -21622,6 +21636,9 @@ void call_user_func(ufunc_T *fp, int argcount, typval_T *argvars, if (do_profiling_yes) { script_prof_restore(&wait_start); } + if (using_sandbox) { + sandbox--; + } if (p_verbose >= 12 && sourcing_name != NULL) { ++no_wait_return; diff --git a/src/nvim/ex_cmds.lua b/src/nvim/ex_cmds.lua index 79ca5363e0..fae21d8c91 100644 --- a/src/nvim/ex_cmds.lua +++ b/src/nvim/ex_cmds.lua @@ -1004,7 +1004,7 @@ return { }, { command='function', - flags=bit.bor(EXTRA, BANG, CMDWIN), + flags=bit.bor(EXTRA, BANG, SBOXOK, CMDWIN), addr_type=ADDR_LINES, func='ex_function', }, From f514b7fbbc75b4464af5abe44d5f859a0d904495 Mon Sep 17 00:00:00 2001 From: Jan Edmund Lazo Date: Sat, 23 Mar 2019 01:26:07 -0400 Subject: [PATCH 02/19] vim-patch:8.1.0189: function defined in sandbox not tested Problem: Function defined in sandbox not tested. Solution: Add a text. https://github.com/vim/vim/commit/d90a144eda047816acffc7a8f297b43a7120710e --- src/nvim/testdir/test_functions.vim | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) diff --git a/src/nvim/testdir/test_functions.vim b/src/nvim/testdir/test_functions.vim index 7dc9f31ce7..292f69d704 100644 --- a/src/nvim/testdir/test_functions.vim +++ b/src/nvim/testdir/test_functions.vim @@ -1037,3 +1037,19 @@ func Test_func_range_with_edit() call delete('Xfuncrange2') bwipe! endfunc + +sandbox function Fsandbox() + normal ix +endfunc + +func Test_func_sandbox() + sandbox let F = {-> 'hello'} + call assert_equal('hello', F()) + + sandbox let F = {-> execute("normal ix\")} + call assert_fails('call F()', 'E48:') + unlet F + + call assert_fails('call Fsandbox()', 'E48:') + delfunc Fsandbox +endfunc From fee1880ea766ffd564e330014348d709a4234d95 Mon Sep 17 00:00:00 2001 From: Jan Edmund Lazo Date: Sat, 23 Mar 2019 08:06:35 -0400 Subject: [PATCH 03/19] vim-patch:8.1.0538: evaluating a modeline might invoke using a shell command Problem: Evaluating a modeline might invoke using a shell command. (Paul Huber) Solution: Set the sandbox flag when setting options from a modeline. https://github.com/vim/vim/commit/5958f95a40a4a44bd9e7f3b7ec6554a6ef3e42ca --- src/nvim/buffer.c | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/src/nvim/buffer.c b/src/nvim/buffer.c index f74c66f106..e9be0b4c42 100644 --- a/src/nvim/buffer.c +++ b/src/nvim/buffer.c @@ -4926,7 +4926,12 @@ chk_modeline ( if (*s != NUL) { /* skip over an empty "::" */ save_SID = current_SID; current_SID = SID_MODELINE; + // Make sure no risky things are executed as a side effect. + sandbox++; + retval = do_set(s, OPT_MODELINE | OPT_LOCAL | flags); + + sandbox--; current_SID = save_SID; if (retval == FAIL) /* stop if error found */ break; From adff3f4dee5e1ab374015fa47676a526099b8a67 Mon Sep 17 00:00:00 2001 From: Abdelhakeem Date: Tue, 26 Mar 2019 18:17:19 +0200 Subject: [PATCH 04/19] vim-patch:8.1.0539: cannot build without the sandbox Problem: Cannot build without the sandbox. Solution: Set the secure option instead of using the sandbox. Also restrict the characters from 'spelllang' that are used for LANG.vim. (suggested by Yasuhiro Matsumoto) https://github.com/vim/vim/commit/82e8c92ebef5afcac0c0fdb706ff163f9b3366f7 --- runtime/doc/options.txt | 2 +- src/nvim/buffer.c | 4 ++-- src/nvim/option.c | 10 ++++++---- 3 files changed, 9 insertions(+), 7 deletions(-) diff --git a/runtime/doc/options.txt b/runtime/doc/options.txt index 534b2025cd..b9eea75e5c 100644 --- a/runtime/doc/options.txt +++ b/runtime/doc/options.txt @@ -5527,7 +5527,7 @@ A jump table for the options with a short description can be found at |Q_op|. After this option has been set successfully, Vim will source the files "spell/LANG.vim" in 'runtimepath'. "LANG" is the value of 'spelllang' - up to the first comma, dot or underscore. + up to the first character that is not an ASCII letter and not a dash. Also see |set-spc-auto|. diff --git a/src/nvim/buffer.c b/src/nvim/buffer.c index e9be0b4c42..ac07af7baa 100644 --- a/src/nvim/buffer.c +++ b/src/nvim/buffer.c @@ -4927,11 +4927,11 @@ chk_modeline ( save_SID = current_SID; current_SID = SID_MODELINE; // Make sure no risky things are executed as a side effect. - sandbox++; + ++secure; retval = do_set(s, OPT_MODELINE | OPT_LOCAL | flags); - sandbox--; + --secure; current_SID = save_SID; if (retval == FAIL) /* stop if error found */ break; diff --git a/src/nvim/option.c b/src/nvim/option.c index a09bd2915d..ef6e71daec 100644 --- a/src/nvim/option.c +++ b/src/nvim/option.c @@ -3291,11 +3291,13 @@ did_set_string_option ( * '.encoding'. */ for (p = q; *p != NUL; ++p) - if (vim_strchr((char_u *)"_.,", *p) != NULL) + if (!ASCII_ISALPHA(*p) && *p != '-') break; - vim_snprintf((char *)fname, sizeof(fname), "spell/%.*s.vim", - (int)(p - q), q); - source_runtime(fname, DIP_ALL); + if (p > q) { + vim_snprintf((char *)fname, sizeof(fname), "spell/%.*s.vim", + (int)(p - q), q); + source_runtime(fname, DIP_ALL); + } } } From 7ddb102292d1ae1b515bcac31df76945d26ac5cd Mon Sep 17 00:00:00 2001 From: Abdelhakeem Date: Tue, 26 Mar 2019 15:09:42 +0200 Subject: [PATCH 05/19] vim-patch:8.1.0540: may evaluate insecure value when appending to option Problem: May evaluate insecure value when appending to option. Solution: Set the secure flag when changing an option that was previously set insecurely. Also allow numbers for the characters from 'spelllang' that are used for LANG.vim. https://github.com/vim/vim/commit/247bb7e43b47eb8407a1111bed60b61aceda52ad --- src/nvim/option.c | 42 ++++++++++++++++++++++++++++++++++-------- 1 file changed, 34 insertions(+), 8 deletions(-) diff --git a/src/nvim/option.c b/src/nvim/option.c index ef6e71daec..c0ba2a733c 100644 --- a/src/nvim/option.c +++ b/src/nvim/option.c @@ -1364,6 +1364,8 @@ do_set ( && nextchar != NUL && !ascii_iswhite(afterchar)) errmsg = e_trailing; } else { + int value_is_replaced = !prepending && !adding && !removing; + if (flags & P_BOOL) { /* boolean */ if (nextchar == '=' || nextchar == ':') { errmsg = e_invarg; @@ -1783,12 +1785,37 @@ do_set ( // buffer is closed by autocommands. saved_newval = (newval != NULL) ? xstrdup((char *)newval) : 0; - // 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); + { + unsigned int *p = insecure_flag(opt_idx, opt_flags); + int did_inc_secure = FALSE; + + // When an option is set in the sandbox, from a + // modeline or in secure mode, then deal with side + // effects in secure mode. Also when the value was + // set with the P_INSECURE flag and is not + // completely replaced. + if (secure +#ifdef HAVE_SANDBOX + || sandbox != 0 +#endif + || (opt_flags & OPT_MODELINE) + || (!value_is_replaced && (*p & P_INSECURE))) + { + did_inc_secure = TRUE; + ++secure; + } + + // 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 (did_inc_secure) { + --secure; + } + } if (errmsg == NULL) { if (!starting) { @@ -1815,8 +1842,7 @@ do_set ( } if (opt_idx >= 0) - did_set_option(opt_idx, opt_flags, - !prepending && !adding && !removing); + did_set_option(opt_idx, opt_flags, value_is_replaced); } skip: From 1d3a1b55d1fb13cb59bdc8fe124159be61d3fa11 Mon Sep 17 00:00:00 2001 From: Abdelhakeem Date: Tue, 26 Mar 2019 13:33:06 +0200 Subject: [PATCH 06/19] vim-patch:8.1.0544: setting 'filetype' in a modeline causes an error Problem: Setting 'filetype' in a modeline causes an error (Hirohito Higashi). Solution: Don't add the P_INSECURE flag when setting 'filetype' from a modeline. Also for 'syntax'. https://github.com/vim/vim/commit/916a818cea5ba05a5f2117407674461b8bee6832 --- src/nvim/option.c | 50 +++++++++++++++--- src/nvim/testdir/test_modeline.vim | 84 ++++++++++++++++++++++++++++++ 2 files changed, 126 insertions(+), 8 deletions(-) create mode 100644 src/nvim/testdir/test_modeline.vim diff --git a/src/nvim/option.c b/src/nvim/option.c index c0ba2a733c..acbe8d791f 100644 --- a/src/nvim/option.c +++ b/src/nvim/option.c @@ -1364,7 +1364,9 @@ do_set ( && nextchar != NUL && !ascii_iswhite(afterchar)) errmsg = e_trailing; } else { + int value_is_replaced = !prepending && !adding && !removing; + int value_checked = false; if (flags & P_BOOL) { /* boolean */ if (nextchar == '=' || nextchar == ':') { @@ -1810,7 +1812,7 @@ do_set ( // 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); + new_value_alloced, oldval, errbuf, opt_flags, &value_checked); if (did_inc_secure) { --secure; @@ -1842,7 +1844,7 @@ do_set ( } if (opt_idx >= 0) - did_set_option(opt_idx, opt_flags, value_is_replaced); + did_set_option(opt_idx, opt_flags, value_is_replaced, value_checked); } skip: @@ -1907,7 +1909,9 @@ static void did_set_option ( int opt_idx, int opt_flags, /* possibly with OPT_MODELINE */ - int new_value /* value was replaced completely */ + int new_value, /* value was replaced completely */ + int value_checked /* value was checked to be safe, no need to + set P_INSECURE */ ) { options[opt_idx].flags |= P_WAS_SET; @@ -1916,9 +1920,9 @@ did_set_option ( * set the P_INSECURE flag. Otherwise, if a new value is stored reset the * flag. */ uint32_t *p = insecure_flag(opt_idx, opt_flags); - if (secure + if (!value_checked && (secure || sandbox != 0 - || (opt_flags & OPT_MODELINE)) + || (opt_flags & OPT_MODELINE))) *p = *p | P_INSECURE; else if (new_value) *p = *p & ~P_INSECURE; @@ -2418,10 +2422,12 @@ static char *set_string_option(const int opt_idx, const char *const value, char *const saved_oldval = xstrdup(oldval); char *const saved_newval = xstrdup(s); + int value_checked = false; char *const r = (char *)did_set_string_option( - opt_idx, (char_u **)varp, (int)true, (char_u *)oldval, NULL, opt_flags); + opt_idx, (char_u **)varp, (int)true, (char_u *)oldval, + NULL, opt_flags, &value_checked); if (r == NULL) { - did_set_option(opt_idx, opt_flags, true); + did_set_option(opt_idx, opt_flags, true, value_checked); } // call autocommand after handling side effects @@ -2463,7 +2469,9 @@ did_set_string_option ( int new_value_alloced, /* new value was allocated */ char_u *oldval, /* previous value of the option */ char_u *errbuf, /* buffer for errors, or NULL */ - int opt_flags /* OPT_LOCAL and/or OPT_GLOBAL */ + int opt_flags, /* OPT_LOCAL and/or OPT_GLOBAL */ + int *value_checked /* value was checked to be safe, no + need to set P_INSECURE */ ) { char_u *errmsg = NULL; @@ -2681,8 +2689,20 @@ did_set_string_option ( if (!valid_filetype(*varp)) { errmsg = e_invarg; } else { + int secure_save = secure; + + // Reset the secure flag, since the value of 'keymap' has + // been checked to be safe. + secure = 0; + // load or unload key mapping tables errmsg = keymap_init(); + + secure = secure_save; + + // Since we check the value, there is no need to set P_INSECURE, + // even when the value comes from a modeline. + *value_checked = true; } if (errmsg == NULL) { @@ -3193,12 +3213,20 @@ did_set_string_option ( errmsg = e_invarg; } else { value_changed = STRCMP(oldval, *varp) != 0; + + // Since we check the value, there is no need to set P_INSECURE, + // even when the value comes from a modeline. + *value_checked = true; } } else if (gvarp == &p_syn) { if (!valid_filetype(*varp)) { errmsg = e_invarg; } else { value_changed = STRCMP(oldval, *varp) != 0; + + // Since we check the value, there is no need to set P_INSECURE, + // even when the value comes from a modeline. + *value_checked = true; } } else if (varp == &curwin->w_p_winhl) { if (!parse_winhl_opt(curwin)) { @@ -3288,6 +3316,11 @@ did_set_string_option ( // already set to this value. if (!(opt_flags & OPT_MODELINE) || value_changed) { static int ft_recursive = 0; + int secure_save = secure; + + // Reset the secure flag, since the value of 'filetype' has + // been checked to be safe. + secure = 0; ft_recursive++; did_filetype = true; @@ -3300,6 +3333,7 @@ did_set_string_option ( if (varp != &(curbuf->b_p_ft)) { varp = NULL; } + secure = secure_save; } } if (varp == &(curwin->w_s->b_p_spl)) { diff --git a/src/nvim/testdir/test_modeline.vim b/src/nvim/testdir/test_modeline.vim new file mode 100644 index 0000000000..75fe1d993c --- /dev/null +++ b/src/nvim/testdir/test_modeline.vim @@ -0,0 +1,84 @@ +func Test_modeline_invalid() + let modeline = &modeline + set modeline + call assert_fails('set Xmodeline', 'E518:') + + let &modeline = modeline + bwipe! + call delete('Xmodeline') + endfunc + +func Test_modeline_filetype() + call writefile(['vim: set ft=c :', 'nothing'], 'Xmodeline_filetype') + let modeline = &modeline + set modeline + filetype plugin on + split Xmodeline_filetype + call assert_equal("c", &filetype) + call assert_equal(1, b:did_ftplugin) + call assert_equal("ccomplete#Complete", &ofu) + + bwipe! + call delete('Xmodeline_filetype') + let &modeline = modeline + filetype plugin off +endfunc + +func Test_modeline_syntax() + call writefile(['vim: set syn=c :', 'nothing'], 'Xmodeline_syntax') + let modeline = &modeline + set modeline + syntax enable + split Xmodeline_syntax + call assert_equal("c", &syntax) + call assert_equal("c", b:current_syntax) + + bwipe! + call delete('Xmodeline_syntax') + let &modeline = modeline + syntax off +endfunc + +func Test_modeline_keymap() + call writefile(['vim: set keymap=greek :', 'nothing'], 'Xmodeline_keymap') + let modeline = &modeline + set modeline + split Xmodeline_keymap + call assert_equal("greek", &keymap) + call assert_match('greek\|grk', b:keymap_name) + + bwipe! + call delete('Xmodeline_keymap') + let &modeline = modeline + set keymap= iminsert=0 imsearch=-1 +endfunc + +func s:modeline_fails(what, text) + let fname = "Xmodeline_fails_" . a:what + call writefile(['vim: set ' . a:text . ' :', 'nothing'], fname) + let modeline = &modeline + set modeline + filetype plugin on + syntax enable + call assert_fails('split ' . fname, 'E474:') + call assert_equal("", &filetype) + call assert_equal("", &syntax) + + bwipe! + call delete(fname) + let &modeline = modeline + filetype plugin off + syntax off +endfunc + +func Test_modeline_filetype_fails() + call s:modeline_fails('filetype', 'ft=evil$CMD') +endfunc + +func Test_modeline_syntax_fails() + call s:modeline_fails('syntax', 'syn=evil$CMD') +endfunc + +func Test_modeline_keymap_fails() + call s:modeline_fails('keymap', 'keymap=evil$CMD') +endfunc From 0ec8da43875a6ed265df466201d1aaaf7c03d379 Mon Sep 17 00:00:00 2001 From: Abdelhakeem Date: Thu, 28 Mar 2019 02:00:34 +0200 Subject: [PATCH 07/19] fixup: use vim_snprintf, ASCII_ISALNUM ASCII_ISALNUM is part of vim-patch:8.1.0540 --- src/nvim/option.c | 65 +++++++++++++++++++++++++---------------------- 1 file changed, 35 insertions(+), 30 deletions(-) diff --git a/src/nvim/option.c b/src/nvim/option.c index acbe8d791f..d4869ea06d 100644 --- a/src/nvim/option.c +++ b/src/nvim/option.c @@ -1812,7 +1812,9 @@ do_set ( // 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, &value_checked); + new_value_alloced, oldval, + errbuf, sizeof(errbuf), + opt_flags, &value_checked); if (did_inc_secure) { --secure; @@ -1921,19 +1923,21 @@ did_set_option ( * flag. */ uint32_t *p = insecure_flag(opt_idx, opt_flags); if (!value_checked && (secure - || sandbox != 0 - || (opt_flags & OPT_MODELINE))) + || sandbox != 0 + || (opt_flags & OPT_MODELINE))) { *p = *p | P_INSECURE; - else if (new_value) + } else if (new_value) { *p = *p & ~P_INSECURE; + } } -static char_u *illegal_char(char_u *errbuf, int c) +static char_u *illegal_char(char_u *errbuf, size_t errbuflen, int c) { - if (errbuf == NULL) + if (errbuf == NULL) { return (char_u *)""; - sprintf((char *)errbuf, _("E539: Illegal character <%s>"), - (char *)transchar(c)); + } + vim_snprintf((char *)errbuf, errbuflen, _("E539: Illegal character <%s>"), + (char *)transchar(c)); return errbuf; } @@ -2425,7 +2429,7 @@ static char *set_string_option(const int opt_idx, const char *const value, int value_checked = false; char *const r = (char *)did_set_string_option( opt_idx, (char_u **)varp, (int)true, (char_u *)oldval, - NULL, opt_flags, &value_checked); + NULL, 0, opt_flags, &value_checked); if (r == NULL) { did_set_option(opt_idx, opt_flags, true, value_checked); } @@ -2463,15 +2467,16 @@ static bool valid_filetype(char_u *val) * Returns NULL for success, or an error message for an error. */ static char_u * -did_set_string_option ( - int opt_idx, /* index in options[] table */ - char_u **varp, /* pointer to the option variable */ - int new_value_alloced, /* new value was allocated */ - char_u *oldval, /* previous value of the option */ - char_u *errbuf, /* buffer for errors, or NULL */ - int opt_flags, /* OPT_LOCAL and/or OPT_GLOBAL */ - int *value_checked /* value was checked to be safe, no - need to set P_INSECURE */ +did_set_string_option( + int opt_idx, // index in options[] table + char_u **varp, // pointer to the option variable + int new_value_alloced, // new value was allocated + char_u *oldval, // previous value of the option + char_u *errbuf, // buffer for errors, or NULL + size_t errbuflen, // length of errors buffer + int opt_flags, // OPT_LOCAL and/or OPT_GLOBAL + int *value_checked // value was checked to be safe, no + // need to set P_INSECURE ) { char_u *errmsg = NULL; @@ -2788,7 +2793,7 @@ did_set_string_option ( while (*s && *s != ':') { if (vim_strchr((char_u *)COM_ALL, *s) == NULL && !ascii_isdigit(*s) && *s != '-') { - errmsg = illegal_char(errbuf, *s); + errmsg = illegal_char(errbuf, errbuflen, *s); break; } ++s; @@ -2840,7 +2845,7 @@ did_set_string_option ( for (s = p_shada; *s; ) { /* Check it's a valid character */ if (vim_strchr((char_u *)"!\"%'/:<@cfhnrs", *s) == NULL) { - errmsg = illegal_char(errbuf, *s); + errmsg = illegal_char(errbuf, errbuflen, *s); break; } if (*s == 'n') { /* name is always last one */ @@ -2860,9 +2865,9 @@ did_set_string_option ( if (!ascii_isdigit(*(s - 1))) { if (errbuf != NULL) { - sprintf((char *)errbuf, - _("E526: Missing number after <%s>"), - transchar_byte(*(s - 1))); + vim_snprintf((char *)errbuf, errbuflen, + _("E526: Missing number after <%s>"), + transchar_byte(*(s - 1))); errmsg = errbuf; } else errmsg = (char_u *)""; @@ -3040,7 +3045,7 @@ did_set_string_option ( if (!*s) break; if (vim_strchr((char_u *)".wbuksid]tU", *s) == NULL) { - errmsg = illegal_char(errbuf, *s); + errmsg = illegal_char(errbuf, errbuflen, *s); break; } if (*++s != NUL && *s != ',' && *s != ' ') { @@ -3054,9 +3059,9 @@ did_set_string_option ( } } else { if (errbuf != NULL) { - sprintf((char *)errbuf, - _("E535: Illegal character after <%c>"), - *--s); + vim_snprintf((char *)errbuf, errbuflen, + _("E535: Illegal character after <%c>"), + *--s); errmsg = errbuf; } else errmsg = (char_u *)""; @@ -3252,7 +3257,7 @@ did_set_string_option ( if (p != NULL) { for (s = *varp; *s; ++s) if (vim_strchr(p, *s) == NULL) { - errmsg = illegal_char(errbuf, *s); + errmsg = illegal_char(errbuf, errbuflen, *s); break; } } @@ -3351,7 +3356,7 @@ did_set_string_option ( * '.encoding'. */ for (p = q; *p != NUL; ++p) - if (!ASCII_ISALPHA(*p) && *p != '-') + if (!ASCII_ISALNUM(*p) && *p != '-') break; if (p > q) { vim_snprintf((char *)fname, sizeof(fname), "spell/%.*s.vim", @@ -3616,7 +3621,7 @@ char_u *check_stl_option(char_u *s) continue; } if (vim_strchr(STL_ALL, *s) == NULL) { - return illegal_char(errbuf, *s); + return illegal_char(errbuf, sizeof(errbuf), *s); } if (*s == '{') { s++; From 9dca0b27df5f71d2818c003870c6d69e0209d178 Mon Sep 17 00:00:00 2001 From: Jan Edmund Lazo Date: Sun, 5 May 2019 11:23:25 -0400 Subject: [PATCH 08/19] vim-patch:8.1.0613: when executing an insecure function the secure flag is stuck Problem: When executing an insecure function the secure flag is stuck. (Gabriel Barta) Solution: Restore "secure" instead of decrementing it. (closes vim/vim#3705) https://github.com/vim/vim/commit/48f377a476e4a3312aa0e3535aba170484b59483 --- src/nvim/buffer.c | 3 ++- src/nvim/option.c | 30 ++++++++++++------------------ src/nvim/testdir/test_autocmd.vim | 23 +++++++++++++++++++++++ 3 files changed, 37 insertions(+), 19 deletions(-) diff --git a/src/nvim/buffer.c b/src/nvim/buffer.c index ac07af7baa..af1a955967 100644 --- a/src/nvim/buffer.c +++ b/src/nvim/buffer.c @@ -4924,6 +4924,7 @@ chk_modeline ( *e = NUL; /* truncate the set command */ if (*s != NUL) { /* skip over an empty "::" */ + const int secure_save = secure; save_SID = current_SID; current_SID = SID_MODELINE; // Make sure no risky things are executed as a side effect. @@ -4931,7 +4932,7 @@ chk_modeline ( retval = do_set(s, OPT_MODELINE | OPT_LOCAL | flags); - --secure; + secure = secure_save; current_SID = save_SID; if (retval == FAIL) /* stop if error found */ break; diff --git a/src/nvim/option.c b/src/nvim/option.c index d4869ea06d..48e230c8ee 100644 --- a/src/nvim/option.c +++ b/src/nvim/option.c @@ -1788,8 +1788,8 @@ do_set ( saved_newval = (newval != NULL) ? xstrdup((char *)newval) : 0; { - unsigned int *p = insecure_flag(opt_idx, opt_flags); - int did_inc_secure = FALSE; + uint32_t *p = insecure_flag(opt_idx, opt_flags); + const int secure_saved = secure; // When an option is set in the sandbox, from a // modeline or in secure mode, then deal with side @@ -1797,29 +1797,23 @@ do_set ( // set with the P_INSECURE flag and is not // completely replaced. if (secure -#ifdef HAVE_SANDBOX - || sandbox != 0 -#endif - || (opt_flags & OPT_MODELINE) - || (!value_is_replaced && (*p & P_INSECURE))) - { - did_inc_secure = TRUE; - ++secure; + || sandbox != 0 + || (opt_flags & OPT_MODELINE) + || (!value_is_replaced && (*p & P_INSECURE))) { + secure++; } - // 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. + // 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, sizeof(errbuf), opt_flags, &value_checked); - if (did_inc_secure) { - --secure; - } - } + secure = secure_saved; + } if (errmsg == NULL) { if (!starting) { diff --git a/src/nvim/testdir/test_autocmd.vim b/src/nvim/testdir/test_autocmd.vim index 253d6750ed..12b6a38ef3 100644 --- a/src/nvim/testdir/test_autocmd.vim +++ b/src/nvim/testdir/test_autocmd.vim @@ -652,6 +652,29 @@ func Test_OptionSet_diffmode_close() "delfunc! AutoCommandOptionSet endfunc +func Test_OptionSet_modeline() + throw 'skipped: Nvim does not support test_override()' + call test_override('starting', 1) + au! OptionSet + augroup set_tabstop + au OptionSet tabstop call timer_start(1, {-> execute("echo 'Handler called'", "")}) + augroup END + call writefile(['vim: set ts=7 sw=5 :', 'something'], 'XoptionsetModeline') + set modeline + let v:errmsg = '' + call assert_fails('split XoptionsetModeline', 'E12:') + call assert_equal(7, &ts) + call assert_equal('', v:errmsg) + + augroup set_tabstop + au! + augroup END + bwipe! + set ts& + call delete('XoptionsetModeline') + call test_override('starting', 0) +endfunc + " Test for Bufleave autocommand that deletes the buffer we are about to edit. func Test_BufleaveWithDelete() new | edit Xfile1 From ad8bba10c493a2ae50592d9be405736e6b018d19 Mon Sep 17 00:00:00 2001 From: Jan Edmund Lazo Date: Sun, 5 May 2019 11:38:34 -0400 Subject: [PATCH 09/19] vim-patch:8.1.1046: the "secure" variable is used inconsistently Problem: the "secure" variable is used inconsistently. (Justin M. Keyes) Solution: Set it to one instead of incrementing. https://github.com/vim/vim/commit/82b033eff82d3ed0da77fd5f5a1c023766acabba --- src/nvim/buffer.c | 2 +- src/nvim/option.c | 5 ++--- 2 files changed, 3 insertions(+), 4 deletions(-) diff --git a/src/nvim/buffer.c b/src/nvim/buffer.c index af1a955967..e3e77d65b0 100644 --- a/src/nvim/buffer.c +++ b/src/nvim/buffer.c @@ -4928,7 +4928,7 @@ chk_modeline ( save_SID = current_SID; current_SID = SID_MODELINE; // Make sure no risky things are executed as a side effect. - ++secure; + secure = 1; retval = do_set(s, OPT_MODELINE | OPT_LOCAL | flags); diff --git a/src/nvim/option.c b/src/nvim/option.c index 48e230c8ee..b6a9b7b322 100644 --- a/src/nvim/option.c +++ b/src/nvim/option.c @@ -1796,11 +1796,10 @@ do_set ( // effects in secure mode. Also when the value was // set with the P_INSECURE flag and is not // completely replaced. - if (secure + if ((opt_flags & OPT_MODELINE) || sandbox != 0 - || (opt_flags & OPT_MODELINE) || (!value_is_replaced && (*p & P_INSECURE))) { - secure++; + secure = 1; } // Handle side effects, and set the global value From a72c05a6f67f9c007649fbc67cf7b63093b7e8a1 Mon Sep 17 00:00:00 2001 From: Jan Edmund Lazo Date: Sat, 25 May 2019 15:01:22 -0400 Subject: [PATCH 10/19] vim-patch:8.1.0205: invalid memory access with invalid modeline Problem: Invalid memory access with invalid modeline. Solution: Pass pointer limit. Add a test. (closes vim/vim#3241) https://github.com/vim/vim/commit/9cf4b5005f12ce1d6692266140bdda05d0312d79 --- src/nvim/option.c | 29 ++++++++++++++++------------- src/nvim/testdir/test_alot.vim | 1 + src/nvim/testdir/test_modeline.vim | 18 +++++++++++------- 3 files changed, 28 insertions(+), 20 deletions(-) diff --git a/src/nvim/option.c b/src/nvim/option.c index b6a9b7b322..667c335eab 100644 --- a/src/nvim/option.c +++ b/src/nvim/option.c @@ -1209,7 +1209,7 @@ do_set ( } len++; if (opt_idx == -1) { - key = find_key_option(arg + 1); + key = find_key_option(arg + 1, true); } } else { len = 0; @@ -1223,7 +1223,7 @@ do_set ( } opt_idx = findoption_len((const char *)arg, (size_t)len); if (opt_idx == -1) { - key = find_key_option(arg); + key = find_key_option(arg, false); } } @@ -1940,10 +1940,12 @@ static char_u *illegal_char(char_u *errbuf, size_t errbuflen, int c) */ static int string_to_key(char_u *arg) { - if (*arg == '<') - return find_key_option(arg + 1); - if (*arg == '^') + if (*arg == '<') { + return find_key_option(arg + 1, true); + } + if (*arg == '^') { return Ctrl_chr(arg[1]); + } return *arg; } @@ -4953,19 +4955,20 @@ char *set_option_value(const char *const name, const long number, return NULL; } -/* - * Translate a string like "t_xx", "" or "" to a key number. - */ -int find_key_option_len(const char_u *arg, size_t len) +// Translate a string like "t_xx", "" or "" to a key number. +// When "has_lt" is true there is a '<' before "*arg_arg". +// Returns 0 when the key is not recognized. +int find_key_option_len(const char_u *arg_arg, size_t len, bool has_lt) { - int key; + int key = 0; int modifiers; + const char_u *arg = arg_arg; // Don't use get_special_key_code() for t_xx, we don't want it to call // add_termcap_entry(). if (len >= 4 && arg[0] == 't' && arg[1] == '_') { key = TERMCAP2KEY(arg[2], arg[3]); - } else { + } else if (has_lt) { arg--; // put arg at the '<' modifiers = 0; key = find_special_key(&arg, len + 1, &modifiers, true, true, false); @@ -4976,9 +4979,9 @@ int find_key_option_len(const char_u *arg, size_t len) return key; } -static int find_key_option(const char_u *arg) +static int find_key_option(const char_u *arg, bool has_lt) { - return find_key_option_len(arg, STRLEN(arg)); + return find_key_option_len(arg, STRLEN(arg), has_lt); } /* diff --git a/src/nvim/testdir/test_alot.vim b/src/nvim/testdir/test_alot.vim index 0602ff6a45..9d81d21623 100644 --- a/src/nvim/testdir/test_alot.vim +++ b/src/nvim/testdir/test_alot.vim @@ -28,6 +28,7 @@ source test_lambda.vim source test_mapping.vim source test_menu.vim source test_messages.vim +source test_modeline.vim source test_move.vim source test_partial.vim source test_popup.vim diff --git a/src/nvim/testdir/test_modeline.vim b/src/nvim/testdir/test_modeline.vim index 75fe1d993c..1d9479407b 100644 --- a/src/nvim/testdir/test_modeline.vim +++ b/src/nvim/testdir/test_modeline.vim @@ -1,11 +1,15 @@ -func Test_modeline_invalid() - let modeline = &modeline - set modeline - call assert_fails('set Xmodeline', 'E518:') +" Tests for parsing the modeline. - let &modeline = modeline - bwipe! - call delete('Xmodeline') +func Test_modeline_invalid() + " This was reading before allocated memory. + call writefile(['vi:0', 'nothing'], 'Xmodeline') + let modeline = &modeline + set modeline + call assert_fails('set Xmodeline', 'E518:') + + let &modeline = modeline + bwipe! + call delete('Xmodeline') endfunc func Test_modeline_filetype() From 6683cb60b805fa305a069cf7873be8b605d78a3d Mon Sep 17 00:00:00 2001 From: Jan Edmund Lazo Date: Sat, 25 May 2019 14:47:17 -0400 Subject: [PATCH 11/19] vim-patch:8.1.0206: duplicate test function name Problem: Duplicate test function name. Solution: Rename both functions. https://github.com/vim/vim/commit/cd96eef3a869557bd3d2d4497861d87cb525db06 --- src/nvim/testdir/test_glob2regpat.vim | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/nvim/testdir/test_glob2regpat.vim b/src/nvim/testdir/test_glob2regpat.vim index fdf17946b6..e6e41f13e7 100644 --- a/src/nvim/testdir/test_glob2regpat.vim +++ b/src/nvim/testdir/test_glob2regpat.vim @@ -1,12 +1,12 @@ " Test glob2regpat() -func Test_invalid() +func Test_glob2regpat_invalid() call assert_fails('call glob2regpat(1.33)', 'E806:') call assert_fails('call glob2regpat("}")', 'E219:') call assert_fails('call glob2regpat("{")', 'E220:') endfunc -func Test_valid() +func Test_glob2regpat_valid() call assert_equal('^foo\.', glob2regpat('foo.*')) call assert_equal('^foo.$', glob2regpat('foo?')) call assert_equal('\.vim$', glob2regpat('*.vim')) From 5cca6f61bb9ae6c2cc7d935e221eec9acf1b6c78 Mon Sep 17 00:00:00 2001 From: Jan Edmund Lazo Date: Sat, 25 May 2019 15:21:09 -0400 Subject: [PATCH 12/19] vim-patch:8.1.0506: modeline test fails when run by root Problem: Modeline test fails when run by root. Solution: Set 'modeline' for the test. (James McCoy, closes vim/vim#3592) https://github.com/vim/vim/commit/9691f82f862ed18c2e3e48f9d2cd902bb947f803 N/A patches: vim-patch:8.1.0208: file left behind after running individual test --- src/nvim/testdir/test_modeline.vim | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/nvim/testdir/test_modeline.vim b/src/nvim/testdir/test_modeline.vim index 1d9479407b..4b3fc2021d 100644 --- a/src/nvim/testdir/test_modeline.vim +++ b/src/nvim/testdir/test_modeline.vim @@ -1,7 +1,7 @@ " Tests for parsing the modeline. func Test_modeline_invalid() - " This was reading before allocated memory. + " This was reading allocated memory in the past. call writefile(['vi:0', 'nothing'], 'Xmodeline') let modeline = &modeline set modeline From 9ab48aac205e887cf10b7587f91121e656e5d2ba Mon Sep 17 00:00:00 2001 From: Jan Edmund Lazo Date: Sat, 25 May 2019 15:40:20 -0400 Subject: [PATCH 13/19] vim-patch:8.1.0546: modeline test with keymap fails Problem: Modeline test with keymap fails. Solution: Check that the keymap feature is available. https://github.com/vim/vim/commit/4ace6ab7e72151d78f1563b23b498ed20fa00211 --- src/nvim/testdir/test_modeline.vim | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/nvim/testdir/test_modeline.vim b/src/nvim/testdir/test_modeline.vim index 4b3fc2021d..c0427e64ab 100644 --- a/src/nvim/testdir/test_modeline.vim +++ b/src/nvim/testdir/test_modeline.vim @@ -44,6 +44,9 @@ func Test_modeline_syntax() endfunc func Test_modeline_keymap() + if !has('keymap') + return + endif call writefile(['vim: set keymap=greek :', 'nothing'], 'Xmodeline_keymap') let modeline = &modeline set modeline From 2c5eede3686efb6f5a2a8e7670752072962cdc10 Mon Sep 17 00:00:00 2001 From: Jan Edmund Lazo Date: Sat, 25 May 2019 15:41:19 -0400 Subject: [PATCH 14/19] vim-patch:8.1.0547: modeline test with keymap still fails Problem: Modeline test with keymap still fails. Solution: Check that the keymap feature is available for the failure assert. https://github.com/vim/vim/commit/3067a4dd0d768d1e4a47cf3c100f3e2b462717d7 --- src/nvim/testdir/test_modeline.vim | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/nvim/testdir/test_modeline.vim b/src/nvim/testdir/test_modeline.vim index c0427e64ab..091a833774 100644 --- a/src/nvim/testdir/test_modeline.vim +++ b/src/nvim/testdir/test_modeline.vim @@ -87,5 +87,8 @@ func Test_modeline_syntax_fails() endfunc func Test_modeline_keymap_fails() + if !has('keymap') + return + endif call s:modeline_fails('keymap', 'keymap=evil$CMD') endfunc From 3bd532ad1568a7548fb95fbe285de668af2a1d90 Mon Sep 17 00:00:00 2001 From: James McCoy Date: Sat, 22 Jun 2019 21:17:53 -0400 Subject: [PATCH 15/19] vim-patch:8.1.1366: using expressions in a modeline is unsafe Problem: Using expressions in a modeline is unsafe. Solution: Disallow using expressions in a modeline, unless the 'modelineexpr' option is set. Update help, add more tests. https://github.com/vim/vim/commit/110289e78195b6d01e1e6ad26ad450de476d41c1 --- runtime/doc/options.txt | 77 +++++++++++++++++------ src/nvim/generators/gen_options.lua | 1 + src/nvim/option.c | 6 ++ src/nvim/option_defs.h | 1 + src/nvim/options.lua | 20 ++++++ src/nvim/testdir/test49.in | 2 +- src/nvim/testdir/test_modeline.vim | 94 ++++++++++++++++++++++++++--- 7 files changed, 174 insertions(+), 27 deletions(-) diff --git a/runtime/doc/options.txt b/runtime/doc/options.txt index b9eea75e5c..827d6bddcf 100644 --- a/runtime/doc/options.txt +++ b/runtime/doc/options.txt @@ -478,14 +478,17 @@ backslash in front of the ':' will be removed. Example: /* vi:set dir=c\:\tmp: */ ~ This sets the 'dir' option to "c:\tmp". Only a single backslash before the ':' is removed. Thus to include "\:" you have to specify "\\:". - + *E992* No other commands than "set" are supported, for security reasons (somebody might create a Trojan horse text file with modelines). And not all options -can be set. For some options a flag is set, so that when it's used the -|sandbox| is effective. Still, there is always a small risk that a modeline -causes trouble. E.g., when some joker sets 'textwidth' to 5 all your lines -are wrapped unexpectedly. So disable modelines before editing untrusted text. -The mail ftplugin does this, for example. +can be set. For some options a flag is set, so that when the value is used +the |sandbox| is effective. Some options can only be set from the modeline +when 'modelineexpr' is set (the default is off). + +Still, there is always a small risk that a modeline causes trouble. E.g., +when some joker sets 'textwidth' to 5 all your lines are wrapped unexpectedly. +So disable modelines before editing untrusted text. The mail ftplugin does +this, for example. Hint: If you would like to do something else than setting an option, you could define an autocommand that checks the file for a specific string. For @@ -2439,7 +2442,7 @@ A jump table for the options with a short description can be found at |Q_op|. The expression will be evaluated in the |sandbox| if set from a modeline, see |sandbox-option|. This option can't be set from a |modeline| when the 'diff' option is - on. + on or the 'modelineexpr' option is off. It is not allowed to change text or jump to another window while evaluating 'foldexpr' |textlock|. @@ -2554,6 +2557,7 @@ A jump table for the options with a short description can be found at |Q_op|. The expression will be evaluated in the |sandbox| if set from a modeline, see |sandbox-option|. + This option cannot be set in a modeline when 'modelineexpr' is off. It is not allowed to change text or jump to another window while evaluating 'foldtext' |textlock|. @@ -2589,16 +2593,8 @@ A jump table for the options with a short description can be found at |Q_op|. The expression will be evaluated in the |sandbox| when set from a modeline, see |sandbox-option|. That stops the option from working, since changing the buffer text is not allowed. - - *'formatoptions'* *'fo'* -'formatoptions' 'fo' string (default: "tcqj", Vi default: "vt") - local to buffer - This is a sequence of letters which describes how automatic - formatting is to be done. See |fo-table|. When the 'paste' option is - on, no formatting is done (like 'formatoptions' is empty). Commas can - be inserted for readability. - To avoid problems with flags that are added in the future, use the - "+=" and "-=" feature of ":set" |add-option-flags|. + This option cannot be set in a modeline when 'modelineexpr' is off. + NOTE: This option is set to "" when 'compatible' is set. *'formatlistpat'* *'flp'* 'formatlistpat' 'flp' string (default: "^\s*\d\+[\]:.)}\t ]\s*") @@ -2613,6 +2609,16 @@ A jump table for the options with a short description can be found at |Q_op|. The default recognizes a number, followed by an optional punctuation character and white space. + *'formatoptions'* *'fo'* +'formatoptions' 'fo' string (default: "tcqj", Vi default: "vt") + local to buffer + This is a sequence of letters which describes how automatic + formatting is to be done. See |fo-table|. When the 'paste' option is + on, no formatting is done (like 'formatoptions' is empty). Commas can + be inserted for readability. + To avoid problems with flags that are added in the future, use the + "+=" and "-=" feature of ":set" |add-option-flags|. + *'formatprg'* *'fp'* 'formatprg' 'fp' string (default "") global or local to buffer |global-local| @@ -2643,6 +2649,9 @@ A jump table for the options with a short description can be found at |Q_op|. - system signals low battery life - Nvim exits abnormally + This option cannot be set from a |modeline| or in the |sandbox|, for + security reasons. + *'gdefault'* *'gd'* *'nogdefault'* *'nogd'* 'gdefault' 'gd' boolean (default off) global @@ -2978,6 +2987,7 @@ A jump table for the options with a short description can be found at |Q_op|. 'guitabtooltip' is used for the tooltip, see below. The expression will be evaluated in the |sandbox| when set from a modeline, see |sandbox-option|. + This option cannot be set in a modeline when 'modelineexpr' is off. Only used when the GUI tab pages line is displayed. 'e' must be present in 'guioptions'. For the non-GUI tab pages line 'tabline' is @@ -3106,6 +3116,7 @@ A jump table for the options with a short description can be found at |Q_op|. When this option contains printf-style '%' items, they will be expanded according to the rules used for 'statusline'. See 'titlestring' for example settings. + This option cannot be set in a modeline when 'modelineexpr' is off. *'ignorecase'* *'ic'* *'noignorecase'* *'noic'* 'ignorecase' 'ic' boolean (default off) @@ -3209,6 +3220,7 @@ A jump table for the options with a short description can be found at |Q_op|. The expression will be evaluated in the |sandbox| when set from a modeline, see |sandbox-option|. + This option cannot be set in a modeline when 'modelineexpr' is off. It is not allowed to change text or jump to another window while evaluating 'includeexpr' |textlock|. @@ -3277,6 +3289,7 @@ A jump table for the options with a short description can be found at |Q_op|. The expression will be evaluated in the |sandbox| when set from a modeline, see |sandbox-option|. + This option cannot be set in a modeline when 'modelineexpr' is off. It is not allowed to change text or jump to another window while evaluating 'indentexpr' |textlock|. @@ -3768,6 +3781,12 @@ A jump table for the options with a short description can be found at |Q_op|. < This option cannot be set from a |modeline| or in the |sandbox|, for security reasons. + *'makespellmem'* *'msm'* +'makespellmem' 'msm' string (default "460000,2000,500") + global + Values relevant only when compressing a spell file, see |spell|. + This option cannot be set from a |modeline| or in the |sandbox|. + *'matchpairs'* *'mps'* 'matchpairs' 'mps' string (default "(:),{:},[:]") local to buffer @@ -3883,6 +3902,17 @@ A jump table for the options with a short description can be found at |Q_op|. 'modeline' 'ml' boolean (Vim default: on (off for root), Vi default: off) local to buffer + If 'modeline' is on 'modelines' gives the number of lines that is + checked for set commands. If 'modeline' is off or 'modelines' is zero + no lines are checked. See |modeline|. + + *'modelineexpr'* *'mle'* *'nomodelineexpr'* *'nomle'* +'modelineexpr' 'mle' boolean (default: off) + global + When on allow some options that are an expression to be set in the + modeline. Check the option for whether it is affected by + 'modelineexpr'. Also see |modeline|. + *'modelines'* *'mls'* 'modelines' 'mls' number (default 5) global @@ -4622,6 +4652,8 @@ A jump table for the options with a short description can be found at |Q_op|. When this option is not empty, it determines the content of the ruler string, as displayed for the 'ruler' option. The format of this option is like that of 'statusline'. + This option cannot be set in a modeline when 'modelineexpr' is off. + The default ruler width is 17 characters. To make the ruler 15 characters wide, put "%15(" at the start and "%)" at the end. Example: > @@ -5252,7 +5284,8 @@ A jump table for the options with a short description can be found at |Q_op|. "Pattern not found", "Back at original", etc. q use "recording" instead of "recording @a" F don't give the file info when editing a file, like `:silent` - was used for the command + was used for the command; note that this also affects messages + from autocommands This gives you the opportunity to avoid that a change between buffers requires you to hit , but still gives as useful a message as @@ -5773,6 +5806,7 @@ A jump table for the options with a short description can be found at |Q_op|. The 'statusline' option will be evaluated in the |sandbox| if set from a modeline, see |sandbox-option|. + This option cannot be set in a modeline when 'modelineexpr' is off. It is not allowed to change text or jump to another window while evaluating 'statusline' |textlock|. @@ -5927,6 +5961,8 @@ A jump table for the options with a short description can be found at |Q_op|. the text to be displayed. Use "%1T" for the first label, "%2T" for the second one, etc. Use "%X" items for closing labels. + This option cannot be set in a modeline when 'modelineexpr' is off. + Keep in mind that only one of the tab pages is the current one, others are invisible and you can't jump to their windows. @@ -6203,8 +6239,11 @@ A jump table for the options with a short description can be found at |Q_op|. global When this option is not empty, it will be used for the title of the window. This happens only when the 'title' option is on. + When this option contains printf-style '%' items, they will be expanded according to the rules used for 'statusline'. + This option cannot be set in a modeline when 'modelineexpr' is off. + Example: > :auto BufEnter * let &titlestring = hostname() . "/" . expand("%:p") :set title titlestring=%<%F%=%l/%L-%P titlelen=70 @@ -6238,6 +6277,8 @@ A jump table for the options with a short description can be found at |Q_op|. undo file that exists is used. When it cannot be read an error is given, no further entry is used. See |undo-persistence|. + This option cannot be set from a |modeline| or in the |sandbox|, for + security reasons. *'undofile'* *'noundofile'* *'udf'* *'noudf'* 'undofile' 'udf' boolean (default off) diff --git a/src/nvim/generators/gen_options.lua b/src/nvim/generators/gen_options.lua index fdc00d5dc0..d9c65e17c5 100644 --- a/src/nvim/generators/gen_options.lua +++ b/src/nvim/generators/gen_options.lua @@ -79,6 +79,7 @@ local get_flags = function(o) {'pri_mkrc'}, {'deny_in_modelines', 'P_NO_ML'}, {'deny_duplicates', 'P_NODUP'}, + {'modelineexpr', 'P_MLE'}, }) do local key_name = flag_desc[1] local def_name = flag_desc[2] or ('P_' .. key_name:upper()) diff --git a/src/nvim/option.c b/src/nvim/option.c index 667c335eab..2b5b8793ca 100644 --- a/src/nvim/option.c +++ b/src/nvim/option.c @@ -251,6 +251,7 @@ typedef struct vimoption { #define P_RWINONLY 0x10000000U ///< only redraw current window #define P_NDNAME 0x20000000U ///< only normal dir name chars allowed #define P_UI_OPTION 0x40000000U ///< send option to remote ui +#define P_MLE 0x80000000U ///< under control of 'modelineexpr' #define HIGHLIGHT_INIT \ "8:SpecialKey,~:EndOfBuffer,z:TermCursor,Z:TermCursorNC,@:NonText," \ @@ -1290,6 +1291,11 @@ do_set ( errmsg = (char_u *)_("E520: Not allowed in a modeline"); goto skip; } + if ((flags & P_MLE) && !p_mle) { + errmsg = (char_u *)_( + "E992: Not allowed in a modeline when 'modelineexpr' is off"); + goto skip; + } /* In diff mode some options are overruled. This avoids that * 'foldmethod' becomes "marker" instead of "diff" and that * "wrap" gets set. */ diff --git a/src/nvim/option_defs.h b/src/nvim/option_defs.h index 82f7fc2107..11a59e95ad 100644 --- a/src/nvim/option_defs.h +++ b/src/nvim/option_defs.h @@ -495,6 +495,7 @@ EXTERN long p_mmd; // 'maxmapdepth' EXTERN long p_mmp; // 'maxmempattern' EXTERN long p_mis; // 'menuitems' EXTERN char_u *p_msm; // 'mkspellmem' +EXTERN long p_mle; // 'modelineexpr' EXTERN long p_mls; // 'modelines' EXTERN char_u *p_mouse; // 'mouse' EXTERN char_u *p_mousem; // 'mousemodel' diff --git a/src/nvim/options.lua b/src/nvim/options.lua index 0cc6f58c5f..7fa2d5bd60 100644 --- a/src/nvim/options.lua +++ b/src/nvim/options.lua @@ -8,6 +8,7 @@ -- defaults={condition=nil, if_true={vi=224, vim=0}, if_false=nil}, -- secure=nil, gettext=nil, noglob=nil, normal_fname_chars=nil, -- pri_mkrc=nil, deny_in_modelines=nil, normal_dname_chars=nil, +-- modelineexpr=nil, -- expand=nil, nodefault=nil, no_mkrc=nil, vi_def=true, vim=true, -- alloced=nil, -- save_pv_indir=nil, @@ -286,6 +287,7 @@ return { deny_duplicates=true, vi_def=true, expand=true, + secure=true, varname='p_cdpath', defaults={if_true={vi=",,"}} }, @@ -856,6 +858,7 @@ return { type='string', scope={'window'}, vi_def=true, vim=true, + modelineexpr=true, alloced=true, redraw={'current_window'}, defaults={if_true={vi="0"}} @@ -931,6 +934,7 @@ return { type='string', scope={'window'}, vi_def=true, vim=true, + modelineexpr=true, alloced=true, redraw={'current_window'}, defaults={if_true={vi="foldtext()"}} @@ -940,6 +944,7 @@ return { type='string', scope={'buffer'}, vi_def=true, vim=true, + modelineexpr=true, alloced=true, varname='p_fex', defaults={if_true={vi=""}} @@ -1053,6 +1058,7 @@ return { full_name='guitablabel', abbreviation='gtl', type='string', scope={'global'}, vi_def=true, + modelineexpr=true, redraw={'current_window'}, enable_if=false, }, @@ -1143,6 +1149,7 @@ return { full_name='iconstring', type='string', scope={'global'}, vi_def=true, + modelineexpr=true, varname='p_iconstring', defaults={if_true={vi=""}} }, @@ -1209,6 +1216,7 @@ return { full_name='includeexpr', abbreviation='inex', type='string', scope={'buffer'}, vi_def=true, + modelineexpr=true, alloced=true, varname='p_inex', defaults={if_true={vi=""}} @@ -1225,6 +1233,7 @@ return { type='string', scope={'buffer'}, vi_def=true, vim=true, + modelineexpr=true, alloced=true, varname='p_inde', defaults={if_true={vi=""}} @@ -1538,6 +1547,13 @@ return { varname='p_ml', defaults={if_true={vi=false, vim=true}} }, + { + full_name='modelineexpr', abbreviation='mle', + type='bool', scope={'global'}, + vi_def=true, + varname='p_mle', + defaults={if_true={vi=false}} + }, { full_name='modelines', abbreviation='mls', type='number', scope={'global'}, @@ -1898,6 +1914,7 @@ return { type='string', scope={'global'}, vi_def=true, alloced=true, + modelineexpr=true, redraw={'statuslines'}, varname='p_ruf', defaults={if_true={vi=""}} @@ -2293,6 +2310,7 @@ return { type='string', scope={'global', 'window'}, vi_def=true, alloced=true, + modelineexpr=true, redraw={'statuslines'}, varname='p_stl', defaults={if_true={vi=""}} @@ -2352,6 +2370,7 @@ return { full_name='tabline', abbreviation='tal', type='string', scope={'global'}, vi_def=true, + modelineexpr=true, redraw={'all_windows'}, varname='p_tal', defaults={if_true={vi=""}} @@ -2511,6 +2530,7 @@ return { full_name='titlestring', type='string', scope={'global'}, vi_def=true, + modelineexpr=true, varname='p_titlestring', defaults={if_true={vi=""}} }, diff --git a/src/nvim/testdir/test49.in b/src/nvim/testdir/test49.in index 435e62765b..eb17ace2fb 100644 --- a/src/nvim/testdir/test49.in +++ b/src/nvim/testdir/test49.in @@ -4,7 +4,7 @@ If after adding a new test, the test output doesn't appear properly in test49.failed, try to add one or more "G"s at the line ending in "test.out" STARTTEST -:se nomore +:se nomore modelineexpr :lang mess C :so test49.vim :" Go back to this file and append the results from register r. diff --git a/src/nvim/testdir/test_modeline.vim b/src/nvim/testdir/test_modeline.vim index 091a833774..8f2c42a6b5 100644 --- a/src/nvim/testdir/test_modeline.vim +++ b/src/nvim/testdir/test_modeline.vim @@ -60,14 +60,17 @@ func Test_modeline_keymap() set keymap= iminsert=0 imsearch=-1 endfunc -func s:modeline_fails(what, text) +func s:modeline_fails(what, text, error) + if !exists('+' . a:what) + return + endif let fname = "Xmodeline_fails_" . a:what call writefile(['vim: set ' . a:text . ' :', 'nothing'], fname) let modeline = &modeline set modeline filetype plugin on syntax enable - call assert_fails('split ' . fname, 'E474:') + call assert_fails('split ' . fname, a:error) call assert_equal("", &filetype) call assert_equal("", &syntax) @@ -79,16 +82,91 @@ func s:modeline_fails(what, text) endfunc func Test_modeline_filetype_fails() - call s:modeline_fails('filetype', 'ft=evil$CMD') + call s:modeline_fails('filetype', 'ft=evil$CMD', 'E474:') endfunc func Test_modeline_syntax_fails() - call s:modeline_fails('syntax', 'syn=evil$CMD') + call s:modeline_fails('syntax', 'syn=evil$CMD', 'E474:') endfunc func Test_modeline_keymap_fails() - if !has('keymap') - return - endif - call s:modeline_fails('keymap', 'keymap=evil$CMD') + call s:modeline_fails('keymap', 'keymap=evil$CMD', 'E474:') +endfunc + +func Test_modeline_fails_always() + call s:modeline_fails('backupdir', 'backupdir=Something()', 'E520:') + call s:modeline_fails('cdpath', 'cdpath=Something()', 'E520:') + call s:modeline_fails('charconvert', 'charconvert=Something()', 'E520:') + call s:modeline_fails('completefunc', 'completefunc=Something()', 'E520:') + call s:modeline_fails('cscopeprg', 'cscopeprg=Something()', 'E520:') + call s:modeline_fails('diffexpr', 'diffexpr=Something()', 'E520:') + call s:modeline_fails('directory', 'directory=Something()', 'E520:') + call s:modeline_fails('equalprg', 'equalprg=Something()', 'E520:') + call s:modeline_fails('errorfile', 'errorfile=Something()', 'E520:') + call s:modeline_fails('exrc', 'exrc=Something()', 'E520:') + call s:modeline_fails('formatprg', 'formatprg=Something()', 'E520:') + call s:modeline_fails('fsync', 'fsync=Something()', 'E520:') + call s:modeline_fails('grepprg', 'grepprg=Something()', 'E520:') + call s:modeline_fails('helpfile', 'helpfile=Something()', 'E520:') + call s:modeline_fails('imactivatefunc', 'imactivatefunc=Something()', 'E520:') + call s:modeline_fails('imstatusfunc', 'imstatusfunc=Something()', 'E520:') + call s:modeline_fails('imstyle', 'imstyle=Something()', 'E520:') + call s:modeline_fails('keywordprg', 'keywordprg=Something()', 'E520:') + call s:modeline_fails('langmap', 'langmap=Something()', 'E520:') + call s:modeline_fails('luadll', 'luadll=Something()', 'E520:') + call s:modeline_fails('makeef', 'makeef=Something()', 'E520:') + call s:modeline_fails('makeprg', 'makeprg=Something()', 'E520:') + call s:modeline_fails('makespellmem', 'makespellmem=Something()', 'E520:') + call s:modeline_fails('mzschemedll', 'mzschemedll=Something()', 'E520:') + call s:modeline_fails('mzschemegcdll', 'mzschemegcdll=Something()', 'E520:') + call s:modeline_fails('omnifunc', 'omnifunc=Something()', 'E520:') + call s:modeline_fails('operatorfunc', 'operatorfunc=Something()', 'E520:') + call s:modeline_fails('perldll', 'perldll=Something()', 'E520:') + call s:modeline_fails('printdevice', 'printdevice=Something()', 'E520:') + call s:modeline_fails('patchexpr', 'patchexpr=Something()', 'E520:') + call s:modeline_fails('printexpr', 'printexpr=Something()', 'E520:') + call s:modeline_fails('pythondll', 'pythondll=Something()', 'E520:') + call s:modeline_fails('pythonhome', 'pythondll=Something()', 'E520:') + call s:modeline_fails('pythonthreedll', 'pythonthreedll=Something()', 'E520:') + call s:modeline_fails('pythonthreehome', 'pythonthreehome=Something()', 'E520:') + call s:modeline_fails('pyxversion', 'pyxversion=Something()', 'E520:') + call s:modeline_fails('rubydll', 'rubydll=Something()', 'E520:') + call s:modeline_fails('runtimepath', 'runtimepath=Something()', 'E520:') + call s:modeline_fails('secure', 'secure=Something()', 'E520:') + call s:modeline_fails('shell', 'shell=Something()', 'E520:') + call s:modeline_fails('shellcmdflag', 'shellcmdflag=Something()', 'E520:') + call s:modeline_fails('shellpipe', 'shellpipe=Something()', 'E520:') + call s:modeline_fails('shellquote', 'shellquote=Something()', 'E520:') + call s:modeline_fails('shellredir', 'shellredir=Something()', 'E520:') + call s:modeline_fails('shellxquote', 'shellxquote=Something()', 'E520:') + call s:modeline_fails('spellfile', 'spellfile=Something()', 'E520:') + call s:modeline_fails('spellsuggest', 'spellsuggest=Something()', 'E520:') + call s:modeline_fails('tcldll', 'tcldll=Something()', 'E520:') + call s:modeline_fails('titleold', 'titleold=Something()', 'E520:') + call s:modeline_fails('viewdir', 'viewdir=Something()', 'E520:') + call s:modeline_fails('viminfo', 'viminfo=Something()', 'E520:') + call s:modeline_fails('viminfofile', 'viminfofile=Something()', 'E520:') + call s:modeline_fails('winptydll', 'winptydll=Something()', 'E520:') + call s:modeline_fails('undodir', 'undodir=Something()', 'E520:') + " only check a few terminal options + " Skip these since nvim doesn't support termcodes as options + "call s:modeline_fails('t_AB', 't_AB=Something()', 'E520:') + "call s:modeline_fails('t_ce', 't_ce=Something()', 'E520:') + "call s:modeline_fails('t_sr', 't_sr=Something()', 'E520:') + "call s:modeline_fails('t_8b', 't_8b=Something()', 'E520:') +endfunc + +func Test_modeline_fails_modelineexpr() + call s:modeline_fails('balloonexpr', 'balloonexpr=Something()', 'E992:') + call s:modeline_fails('foldexpr', 'foldexpr=Something()', 'E992:') + call s:modeline_fails('foldtext', 'foldtext=Something()', 'E992:') + call s:modeline_fails('formatexpr', 'formatexpr=Something()', 'E992:') + call s:modeline_fails('guitablabel', 'guitablabel=Something()', 'E992:') + call s:modeline_fails('iconstring', 'iconstring=Something()', 'E992:') + call s:modeline_fails('includeexpr', 'includeexpr=Something()', 'E992:') + call s:modeline_fails('indentexpr', 'indentexpr=Something()', 'E992:') + call s:modeline_fails('rulerformat', 'rulerformat=Something()', 'E992:') + call s:modeline_fails('statusline', 'statusline=Something()', 'E992:') + call s:modeline_fails('tabline', 'tabline=Something()', 'E992:') + call s:modeline_fails('titlestring', 'titlestring=Something()', 'E992:') endfunc From 536e9320a01f06e2be2f2a9097da4be4a2b8241e Mon Sep 17 00:00:00 2001 From: James McCoy Date: Sat, 22 Jun 2019 22:06:30 -0400 Subject: [PATCH 16/19] vim-patch:8.1.1367: can set 'modelineexpr' in modeline Problem: can set 'modelineexpr' in modeline. Solution: Add P_SECURE flag. https://github.com/vim/vim/commit/7e800c6047c8a9cc3e5cbc019a4dc91ec36616b1 --- src/nvim/options.lua | 1 + src/nvim/testdir/test_modeline.vim | 1 + 2 files changed, 2 insertions(+) diff --git a/src/nvim/options.lua b/src/nvim/options.lua index 7fa2d5bd60..7ca1b4d64e 100644 --- a/src/nvim/options.lua +++ b/src/nvim/options.lua @@ -1551,6 +1551,7 @@ return { full_name='modelineexpr', abbreviation='mle', type='bool', scope={'global'}, vi_def=true, + secure=true, varname='p_mle', defaults={if_true={vi=false}} }, diff --git a/src/nvim/testdir/test_modeline.vim b/src/nvim/testdir/test_modeline.vim index 8f2c42a6b5..8cd6e552e7 100644 --- a/src/nvim/testdir/test_modeline.vim +++ b/src/nvim/testdir/test_modeline.vim @@ -119,6 +119,7 @@ func Test_modeline_fails_always() call s:modeline_fails('makespellmem', 'makespellmem=Something()', 'E520:') call s:modeline_fails('mzschemedll', 'mzschemedll=Something()', 'E520:') call s:modeline_fails('mzschemegcdll', 'mzschemegcdll=Something()', 'E520:') + call s:modeline_fails('modelineexpr', 'modelineexpr=Something()', 'E520:') call s:modeline_fails('omnifunc', 'omnifunc=Something()', 'E520:') call s:modeline_fails('operatorfunc', 'operatorfunc=Something()', 'E520:') call s:modeline_fails('perldll', 'perldll=Something()', 'E520:') From 1bb1b5087e839c06d95d25758ec5380c331a7664 Mon Sep 17 00:00:00 2001 From: James McCoy Date: Sat, 22 Jun 2019 22:08:57 -0400 Subject: [PATCH 17/19] vim-patch:8.1.1368: modeline test fails with python but without pythonhome Problem: Modeline test fails with python but without pythonhome. Solution: Correct test argument. https://github.com/vim/vim/commit/e09244ee3567d658c293fb1ae0d47a1a8be870ac --- src/nvim/testdir/test_modeline.vim | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/nvim/testdir/test_modeline.vim b/src/nvim/testdir/test_modeline.vim index 8cd6e552e7..e1d56727fe 100644 --- a/src/nvim/testdir/test_modeline.vim +++ b/src/nvim/testdir/test_modeline.vim @@ -127,7 +127,7 @@ func Test_modeline_fails_always() call s:modeline_fails('patchexpr', 'patchexpr=Something()', 'E520:') call s:modeline_fails('printexpr', 'printexpr=Something()', 'E520:') call s:modeline_fails('pythondll', 'pythondll=Something()', 'E520:') - call s:modeline_fails('pythonhome', 'pythondll=Something()', 'E520:') + call s:modeline_fails('pythonhome', 'pythonhome=Something()', 'E520:') call s:modeline_fails('pythonthreedll', 'pythonthreedll=Something()', 'E520:') call s:modeline_fails('pythonthreehome', 'pythonthreehome=Something()', 'E520:') call s:modeline_fails('pyxversion', 'pyxversion=Something()', 'E520:') From 13f3a21226fdd31c42ba927ff12ac6c34c940311 Mon Sep 17 00:00:00 2001 From: James McCoy Date: Sat, 22 Jun 2019 22:09:32 -0400 Subject: [PATCH 18/19] vim-patch:8.1.1382: error when editing test file Problem: Error when editing test file. Solution: Remove part of modeline. https://github.com/vim/vim/commit/3020a87cb121123abf1e9a1eca0eddac241fc481 --- src/nvim/testdir/test49.in | 2 +- src/nvim/testdir/test49.vim | 3 +-- src/nvim/testdir/test_vimscript.vim | 1 - 3 files changed, 2 insertions(+), 4 deletions(-) diff --git a/src/nvim/testdir/test49.in b/src/nvim/testdir/test49.in index eb17ace2fb..435e62765b 100644 --- a/src/nvim/testdir/test49.in +++ b/src/nvim/testdir/test49.in @@ -4,7 +4,7 @@ If after adding a new test, the test output doesn't appear properly in test49.failed, try to add one or more "G"s at the line ending in "test.out" STARTTEST -:se nomore modelineexpr +:se nomore :lang mess C :so test49.vim :" Go back to this file and append the results from register r. diff --git a/src/nvim/testdir/test49.vim b/src/nvim/testdir/test49.vim index 467abcd9b9..837e55ebca 100644 --- a/src/nvim/testdir/test49.vim +++ b/src/nvim/testdir/test49.vim @@ -1,6 +1,6 @@ " Vim script language tests " Author: Servatius Brandt -" Last Change: 2016 Feb 07 +" Last Change: 2019 May 24 "------------------------------------------------------------------------------- " Test environment {{{1 @@ -9005,5 +9005,4 @@ Xcheck 50443995 "------------------------------------------------------------------------------- " Modelines {{{1 " vim: ts=8 sw=4 tw=80 fdm=marker -" vim: fdt=substitute(substitute(foldtext(),\ '\\%(^+--\\)\\@<=\\(\\s*\\)\\(.\\{-}\\)\:\ \\%(\"\ \\)\\=\\(Test\ \\d*\\)\:\\s*',\ '\\3\ (\\2)\:\ \\1',\ \"\"),\ '\\(Test\\s*\\)\\(\\d\\)\\D\\@=',\ '\\1\ \\2',\ "") "------------------------------------------------------------------------------- diff --git a/src/nvim/testdir/test_vimscript.vim b/src/nvim/testdir/test_vimscript.vim index 5b16f6d205..c856fd720c 100644 --- a/src/nvim/testdir/test_vimscript.vim +++ b/src/nvim/testdir/test_vimscript.vim @@ -1297,5 +1297,4 @@ endfunc "------------------------------------------------------------------------------- " Modelines {{{1 " vim: ts=8 sw=4 tw=80 fdm=marker -" vim: fdt=substitute(substitute(foldtext(),\ '\\%(^+--\\)\\@<=\\(\\s*\\)\\(.\\{-}\\)\:\ \\%(\"\ \\)\\=\\(Test\ \\d*\\)\:\\s*',\ '\\3\ (\\2)\:\ \\1',\ \"\"),\ '\\(Test\\s*\\)\\(\\d\\)\\D\\@=',\ '\\1\ \\2',\ "") "------------------------------------------------------------------------------- From 959ff84e04d41806963cb476d6a731f4ef1c0215 Mon Sep 17 00:00:00 2001 From: James McCoy Date: Sat, 22 Jun 2019 22:11:52 -0400 Subject: [PATCH 19/19] vim-patch:8.1.1401: misspelled mkspellmem as makespellmem Problem: Misspelled mkspellmem as makespellmem. Solution: Drop duplicate help entry, fix test. (Naruhiko Nishino, Ken Takata, closes vim/vim#4437) https://github.com/vim/vim/commit/076073950c44ea0e35bc39d539dc7ab41bf9c7ec --- runtime/doc/options.txt | 8 ++------ src/nvim/testdir/test_modeline.vim | 2 +- 2 files changed, 3 insertions(+), 7 deletions(-) diff --git a/runtime/doc/options.txt b/runtime/doc/options.txt index 827d6bddcf..e8471d561a 100644 --- a/runtime/doc/options.txt +++ b/runtime/doc/options.txt @@ -3781,12 +3781,6 @@ A jump table for the options with a short description can be found at |Q_op|. < This option cannot be set from a |modeline| or in the |sandbox|, for security reasons. - *'makespellmem'* *'msm'* -'makespellmem' 'msm' string (default "460000,2000,500") - global - Values relevant only when compressing a spell file, see |spell|. - This option cannot be set from a |modeline| or in the |sandbox|. - *'matchpairs'* *'mps'* 'matchpairs' 'mps' string (default "(:),{:},[:]") local to buffer @@ -3898,6 +3892,8 @@ A jump table for the options with a short description can be found at |Q_op|. < If you have less than 512 Mbyte |:mkspell| may fail for some languages, no matter what you set 'mkspellmem' to. + This option cannot be set from a |modeline| or in the |sandbox|. + *'modeline'* *'ml'* *'nomodeline'* *'noml'* 'modeline' 'ml' boolean (Vim default: on (off for root), Vi default: off) diff --git a/src/nvim/testdir/test_modeline.vim b/src/nvim/testdir/test_modeline.vim index e1d56727fe..1e196e07f0 100644 --- a/src/nvim/testdir/test_modeline.vim +++ b/src/nvim/testdir/test_modeline.vim @@ -116,7 +116,7 @@ func Test_modeline_fails_always() call s:modeline_fails('luadll', 'luadll=Something()', 'E520:') call s:modeline_fails('makeef', 'makeef=Something()', 'E520:') call s:modeline_fails('makeprg', 'makeprg=Something()', 'E520:') - call s:modeline_fails('makespellmem', 'makespellmem=Something()', 'E520:') + call s:modeline_fails('mkspellmem', 'mkspellmem=Something()', 'E520:') call s:modeline_fails('mzschemedll', 'mzschemedll=Something()', 'E520:') call s:modeline_fails('mzschemegcdll', 'mzschemegcdll=Something()', 'E520:') call s:modeline_fails('modelineexpr', 'modelineexpr=Something()', 'E520:')