diff options
-rw-r--r-- | src/nvim/option.c | 44 | ||||
-rw-r--r-- | src/nvim/path.c | 16 | ||||
-rw-r--r-- | src/nvim/spell.c | 4 | ||||
-rw-r--r-- | src/nvim/testdir/test_escaped_glob.vim | 2 | ||||
-rw-r--r-- | src/nvim/testdir/test_spell.vim | 11 | ||||
-rw-r--r-- | test/functional/legacy/097_glob_path_spec.lua | 2 |
6 files changed, 71 insertions, 8 deletions
diff --git a/src/nvim/option.c b/src/nvim/option.c index f03dcc2bf2..52742c8b64 100644 --- a/src/nvim/option.c +++ b/src/nvim/option.c @@ -2509,12 +2509,41 @@ static char *set_string_option(const int opt_idx, const char *const value, return r; } +/// Return true if "val" is a valid name: only consists of alphanumeric ASCII +/// characters or characters in "allowed". +static bool valid_name(const char_u *val, const char *allowed) + FUNC_ATTR_NONNULL_ALL FUNC_ATTR_PURE FUNC_ATTR_WARN_UNUSED_RESULT +{ + for (const char_u *s = val; *s != NUL; s++) { + if (!ASCII_ISALNUM(*s) + && vim_strchr((const char_u *)allowed, *s) == NULL) { + return false; + } + } + return true; +} + /// Return true if "val" is a valid 'filetype' name. /// Also used for 'syntax' and 'keymap'. -static bool valid_filetype(char_u *val) +static bool valid_filetype(const char_u *val) + FUNC_ATTR_NONNULL_ALL FUNC_ATTR_PURE FUNC_ATTR_WARN_UNUSED_RESULT { - for (char_u *s = val; *s != NUL; s++) { - if (!ASCII_ISALNUM(*s) && vim_strchr((char_u *)".-_", *s) == NULL) { + return valid_name(val, ".-_"); +} + +/// Return true if "val" is a valid 'spellang' value. +bool valid_spellang(const char_u *val) + FUNC_ATTR_NONNULL_ALL FUNC_ATTR_PURE FUNC_ATTR_WARN_UNUSED_RESULT +{ + return valid_name(val, ".-_,"); +} + +/// Return true if "val" is a valid 'spellfile' value. +static bool valid_spellfile(const char_u *val) + FUNC_ATTR_NONNULL_ALL FUNC_ATTR_PURE FUNC_ATTR_WARN_UNUSED_RESULT +{ + for (const char_u *s = val; *s != NUL; s++) { + if (!vim_isfilec(*s) && *s != ',') { return false; } } @@ -3032,7 +3061,14 @@ ambw_end: || varp == &(curwin->w_s->b_p_spf)) { // When 'spelllang' or 'spellfile' is set and there is a window for this // buffer in which 'spell' is set load the wordlists. - errmsg = did_set_spell_option(varp == &(curwin->w_s->b_p_spf)); + const bool is_spellfile = varp == &(curwin->w_s->b_p_spf); + + if ((is_spellfile && !valid_spellfile(*varp)) + || (!is_spellfile && !valid_spellang(*varp))) { + errmsg = e_invarg; + } else { + errmsg = did_set_spell_option(is_spellfile); + } } else if (varp == &(curwin->w_s->b_p_spc)) { // When 'spellcapcheck' is set compile the regexp program. errmsg = compile_cap_prog(curwin->w_s); diff --git a/src/nvim/path.c b/src/nvim/path.c index a53870acb8..0142724a5b 100644 --- a/src/nvim/path.c +++ b/src/nvim/path.c @@ -1120,10 +1120,22 @@ static bool has_env_var(char_u *p) static bool has_special_wildchar(char_u *p) { for (; *p; MB_PTR_ADV(p)) { - // Allow for escaping - if (*p == '\\' && p[1] != NUL) { + // Disallow line break characters. + if (*p == '\r' || *p == '\n') { + break; + } + // Allow for escaping. + if (*p == '\\' && p[1] != NUL && p[1] != '\r' && p[1] != '\n') { p++; } else if (vim_strchr((char_u *)SPECIAL_WILDCHAR, *p) != NULL) { + // A { must be followed by a matching }. + if (*p == '{' && vim_strchr(p, '}') == NULL) { + continue; + } + // A quote and backtick must be followed by another one. + if ((*p == '`' || *p == '\'') && vim_strchr(p, *p) == NULL) { + continue; + } return true; } } diff --git a/src/nvim/spell.c b/src/nvim/spell.c index c75a53a777..a221f3fd75 100644 --- a/src/nvim/spell.c +++ b/src/nvim/spell.c @@ -2008,6 +2008,10 @@ char_u *did_set_spelllang(win_T *wp) region = NULL; len = (int)STRLEN(lang); + if (!valid_spellang(lang)) { + continue; + } + if (STRCMP(lang, "cjk") == 0) { wp->w_s->b_cjk = 1; continue; diff --git a/src/nvim/testdir/test_escaped_glob.vim b/src/nvim/testdir/test_escaped_glob.vim index aad3a1e835..2bfd82c296 100644 --- a/src/nvim/testdir/test_escaped_glob.vim +++ b/src/nvim/testdir/test_escaped_glob.vim @@ -17,7 +17,7 @@ function Test_glob() " Setting 'shell' to an invalid name causes a memory leak. sandbox call assert_equal("", glob('Xxx\{')) sandbox call assert_equal("", glob('Xxx\$')) - w! Xxx{ + w! Xxx\{ " } to fix highlighting w! Xxx\$ sandbox call assert_equal("Xxx{", glob('Xxx\{')) diff --git a/src/nvim/testdir/test_spell.vim b/src/nvim/testdir/test_spell.vim index e2016d7927..94789d6ea3 100644 --- a/src/nvim/testdir/test_spell.vim +++ b/src/nvim/testdir/test_spell.vim @@ -151,6 +151,12 @@ func Test_spellinfo() set nospell spelllang=en call assert_fails('spellinfo', 'E756:') + call assert_fails('set spelllang=foo/bar', 'E474:') + call assert_fails('set spelllang=foo\ bar', 'E474:') + call assert_fails("set spelllang=foo\\\nbar", 'E474:') + call assert_fails("set spelllang=foo\\\rbar", 'E474:') + call assert_fails("set spelllang=foo+bar", 'E474:') + set enc& spell& spelllang& bwipe endfunc @@ -386,6 +392,11 @@ func Test_zz_sal_and_addition() call assert_equal("elekwint", SecondSpellWord()) endfunc +func Test_spellfile_value() + set spellfile=Xdir/Xtest.latin1.add + set spellfile=Xdir/Xtest.utf-8.add,Xtest_other.add +endfunc + func Test_region_error() messages clear call writefile(["/regions=usgbnz", "elequint/0"], "Xtest.latin1.add") diff --git a/test/functional/legacy/097_glob_path_spec.lua b/test/functional/legacy/097_glob_path_spec.lua index ccd93fed60..dd5a26ad3b 100644 --- a/test/functional/legacy/097_glob_path_spec.lua +++ b/test/functional/legacy/097_glob_path_spec.lua @@ -52,7 +52,7 @@ describe('glob() and globpath()', function() command([[$put =glob('Xxx\{')]]) command([[$put =glob('Xxx\$')]]) - command('silent w! Xxx{') + command('silent w! Xxx\\{') command([[w! Xxx\$]]) command([[$put =glob('Xxx\{')]]) command([[$put =glob('Xxx\$')]]) |