diff options
-rw-r--r-- | src/nvim/mbyte.c | 25 | ||||
-rw-r--r-- | src/nvim/spellfile.c | 11 | ||||
-rw-r--r-- | src/nvim/testdir/test_spell.vim | 8 | ||||
-rw-r--r-- | src/nvim/testdir/test_spell_utf8.vim | 6 |
4 files changed, 42 insertions, 8 deletions
diff --git a/src/nvim/mbyte.c b/src/nvim/mbyte.c index 1d65529b75..37b4af5172 100644 --- a/src/nvim/mbyte.c +++ b/src/nvim/mbyte.c @@ -1992,6 +1992,31 @@ theend: convert_setup(&vimconv, NULL, NULL); } +/// @return true if string "s" is a valid utf-8 string. +/// When "end" is NULL stop at the first NUL. +/// When "end" is positive stop there. +bool utf_valid_string(const char_u *s, const char_u *end) +{ + const char_u *p = s; + + while (end == NULL ? *p != NUL : p < end) { + int l = utf8len_tab_zero[*p]; + if (l == 0) { + return false; // invalid lead byte + } + if (end != NULL && p + l > end) { + return false; // incomplete byte sequence + } + p++; + while (--l > 0) { + if ((*p++ & 0xc0) != 0x80) { + return false; // invalid trail byte + } + } + } + return true; +} + /* * If the cursor moves on an trail byte, set the cursor on the lead byte. * Thus it moves left if necessary. diff --git a/src/nvim/spellfile.c b/src/nvim/spellfile.c index b7ee3e7374..3a2f29ba1a 100644 --- a/src/nvim/spellfile.c +++ b/src/nvim/spellfile.c @@ -302,6 +302,7 @@ #define CF_UPPER 0x02 static char *e_spell_trunc = N_("E758: Truncated spell file"); +static char *e_illegal_character_in_word = N_("E1280: Illegal character in word"); static char *e_afftrailing = N_("Trailing text in %s line %d: %s"); static char *e_affname = N_("Affix name too long in %s line %d: %s"); static char *msg_compressing = N_("Compressing word tree..."); @@ -3927,6 +3928,11 @@ static int store_word(spellinfo_T *spin, char_u *word, int flags, int region, co char_u foldword[MAXWLEN]; int res = OK; + // Avoid adding illegal bytes to the word tree. + if (!utf_valid_string(word, NULL)) { + return FAIL; + } + (void)spell_casefold(curwin, word, len, foldword, MAXWLEN); for (const char_u *p = pfxlist; res == OK; p++) { if (!need_affix || (p != NULL && *p != NUL)) { @@ -5525,6 +5531,11 @@ void spell_add_word(char_u *word, int len, SpellAddType what, int idx, bool undo int i; char_u *spf; + if (!utf_valid_string(word, NULL)) { + emsg(_(e_illegal_character_in_word)); + return; + } + if (idx == 0) { // use internal wordlist if (int_wordlist == NULL) { int_wordlist = vim_tempname(); diff --git a/src/nvim/testdir/test_spell.vim b/src/nvim/testdir/test_spell.vim index 56ed97cdd9..ce21b8bdc9 100644 --- a/src/nvim/testdir/test_spell.vim +++ b/src/nvim/testdir/test_spell.vim @@ -776,14 +776,6 @@ func Test_spell_screendump() call delete('XtestSpell') endfunc -func Test_spell_single_word() - new - silent! norm 0R00 - spell! ß - silent 0norm 0r$ Dvz= - bwipe! -endfunc - let g:test_data_aff1 = [ \"SET ISO8859-1", \"TRY esianrtolcdugmphbyfvkwjkqxz-\xEB\xE9\xE8\xEA\xEF\xEE\xE4\xE0\xE2\xF6\xFC\xFB'ESIANRTOLCDUGMPHBYFVKWJKQXZ", diff --git a/src/nvim/testdir/test_spell_utf8.vim b/src/nvim/testdir/test_spell_utf8.vim index 3d159f3352..1d323df67e 100644 --- a/src/nvim/testdir/test_spell_utf8.vim +++ b/src/nvim/testdir/test_spell_utf8.vim @@ -768,4 +768,10 @@ func Test_spellfile_value() set spellfile=Xdir/Xtest.utf-8.add,Xtest_other.add endfunc +" Invalid bytes may cause trouble when creating the word list. +func Test_check_for_valid_word() + call assert_fails("spellgood! 0\xac", 'E1280:') +endfunc + + " vim: shiftwidth=2 sts=2 expandtab |