aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/nvim/mbyte.c25
-rw-r--r--src/nvim/spellfile.c11
-rw-r--r--src/nvim/testdir/test_spell.vim8
-rw-r--r--src/nvim/testdir/test_spell_utf8.vim6
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