diff options
author | James McCoy <jamessan@jamessan.com> | 2017-03-10 17:26:22 -0500 |
---|---|---|
committer | James McCoy <jamessan@jamessan.com> | 2017-03-11 20:32:38 -0500 |
commit | 2ed2b1d505cc028347b579f677eb8e6bde9dacdd (patch) | |
tree | 90636600427eae51716a16beb659fe7dd8cb2192 | |
parent | eaf1f9b9dc62b2201fa54374a88029de1b3f94fb (diff) | |
download | rneovim-2ed2b1d505cc028347b579f677eb8e6bde9dacdd.tar.gz rneovim-2ed2b1d505cc028347b579f677eb8e6bde9dacdd.tar.bz2 rneovim-2ed2b1d505cc028347b579f677eb8e6bde9dacdd.zip |
vim-patch:7.4.2223
Problem: Buffer overflow when using latin1 character with feedkeys().
Solution: Check for an illegal character. Add a test.
https://github.com/vim/vim/commit/d3c907b5d2b352482b580a0cf687cbbea4c19ea1
-rw-r--r-- | src/nvim/eval.c | 6 | ||||
-rw-r--r-- | src/nvim/getchar.c | 19 | ||||
-rw-r--r-- | src/nvim/macros.h | 2 | ||||
-rw-r--r-- | src/nvim/spell.c | 22 | ||||
-rw-r--r-- | src/nvim/testdir/test_alot.vim | 1 | ||||
-rw-r--r-- | src/nvim/testdir/test_regexp_utf8.vim | 15 | ||||
-rw-r--r-- | src/nvim/testdir/test_source_utf8.vim | 33 | ||||
-rw-r--r-- | src/nvim/version.c | 2 |
8 files changed, 57 insertions, 43 deletions
diff --git a/src/nvim/eval.c b/src/nvim/eval.c index 6dc7e5606e..bcad6df337 100644 --- a/src/nvim/eval.c +++ b/src/nvim/eval.c @@ -16932,7 +16932,7 @@ static void f_strgetchar(typval_T *argvars, typval_T *rettv, FunPtr fptr) break; } charidx--; - byteidx += mb_cptr2len(str + byteidx); + byteidx += MB_CPTR2LEN(str + byteidx); } } } @@ -17054,7 +17054,7 @@ static void f_strcharpart(typval_T *argvars, typval_T *rettv, FunPtr fptr) { if (!error) { if (nchar > 0) { while (nchar > 0 && nbyte < slen) { - nbyte += mb_cptr2len(p + nbyte); + nbyte += MB_CPTR2LEN(p + nbyte); nchar--; } } else { @@ -17069,7 +17069,7 @@ static void f_strcharpart(typval_T *argvars, typval_T *rettv, FunPtr fptr) { if (off < 0) { len += 1; } else { - len += mb_cptr2len(p + off); + len += MB_CPTR2LEN(p + off); } charlen--; } diff --git a/src/nvim/getchar.c b/src/nvim/getchar.c index 46c1e89c31..2a5454cb92 100644 --- a/src/nvim/getchar.c +++ b/src/nvim/getchar.c @@ -3746,8 +3746,10 @@ eval_map_expr ( */ char_u *vim_strsave_escape_csi(char_u *p) { - /* Need a buffer to hold up to three times as much. */ - char_u *res = xmalloc(STRLEN(p) * 3 + 1); + // Need a buffer to hold up to three times as much. Four in case of an + // illegal utf-8 byte: + // 0xc0 -> 0xc3 - 0x80 -> 0xc3 K_SPECIAL KS_SPECIAL KE_FILLER + char_u *res = xmalloc(STRLEN(p) * 4 + 1); char_u *d = res; for (char_u *s = p; *s != NUL; ) { if (s[0] == K_SPECIAL && s[1] != NUL && s[2] != NUL) { @@ -3756,17 +3758,10 @@ char_u *vim_strsave_escape_csi(char_u *p) *d++ = *s++; *d++ = *s++; } else { - int len = mb_char2len(PTR2CHAR(s)); - int len2 = mb_ptr2len(s); - /* Add character, possibly multi-byte to destination, escaping - * CSI and K_SPECIAL. */ + // Add character, possibly multi-byte to destination, escaping + // CSI and K_SPECIAL. Be careful, it can be an illegal byte! d = add_char2buf(PTR2CHAR(s), d); - while (len < len2) { - /* add following combining char */ - d = add_char2buf(PTR2CHAR(s + len), d); - len += mb_char2len(PTR2CHAR(s + len)); - } - mb_ptr_adv(s); + s += MB_CPTR2LEN(s); } } *d = NUL; diff --git a/src/nvim/macros.h b/src/nvim/macros.h index df2b431e92..650bf76156 100644 --- a/src/nvim/macros.h +++ b/src/nvim/macros.h @@ -138,7 +138,7 @@ // Backup multi-byte pointer. Only use with "p" > "s" ! # define mb_ptr_back(s, p) (p -= mb_head_off((char_u *)s, (char_u *)p - 1) + 1) // get length of multi-byte char, not including composing chars -# define mb_cptr2len(p) utf_ptr2len(p) +# define MB_CPTR2LEN(p) utf_ptr2len(p) # define MB_COPY_CHAR(f, t) mb_copy_char((const char_u **)(&f), &t); diff --git a/src/nvim/spell.c b/src/nvim/spell.c index dd4bb1a56b..c1bb77fd90 100644 --- a/src/nvim/spell.c +++ b/src/nvim/spell.c @@ -4507,7 +4507,7 @@ static void suggest_trie_walk(suginfo_T *su, langp_T *lp, char_u *fword, bool so } if (has_mbyte) { - n = mb_cptr2len(p); + n = MB_CPTR2LEN(p); c = mb_ptr2char(p); if (p[n] == NUL) c2 = NUL; @@ -4584,9 +4584,9 @@ static void suggest_trie_walk(suginfo_T *su, langp_T *lp, char_u *fword, bool so // "fword" here, it's changed back afterwards at STATE_UNSWAP3. p = fword + sp->ts_fidx; if (has_mbyte) { - n = mb_cptr2len(p); + n = MB_CPTR2LEN(p); c = mb_ptr2char(p); - fl = mb_cptr2len(p + n); + fl = MB_CPTR2LEN(p + n); c2 = mb_ptr2char(p + n); if (!soundfold && !spell_iswordp(p + n + fl, curwin)) c3 = c; // don't swap non-word char @@ -4682,10 +4682,10 @@ static void suggest_trie_walk(suginfo_T *su, langp_T *lp, char_u *fword, bool so ++depth; p = fword + sp->ts_fidx; if (has_mbyte) { - n = mb_cptr2len(p); + n = MB_CPTR2LEN(p); c = mb_ptr2char(p); - fl = mb_cptr2len(p + n); - fl += mb_cptr2len(p + n + fl); + fl = MB_CPTR2LEN(p + n); + fl += MB_CPTR2LEN(p + n + fl); memmove(p, p + n, fl); mb_char2bytes(c, p + fl); stack[depth].ts_fidxtry = sp->ts_fidx + n + fl; @@ -4734,10 +4734,10 @@ static void suggest_trie_walk(suginfo_T *su, langp_T *lp, char_u *fword, bool so ++depth; p = fword + sp->ts_fidx; if (has_mbyte) { - n = mb_cptr2len(p); - n += mb_cptr2len(p + n); + n = MB_CPTR2LEN(p); + n += MB_CPTR2LEN(p + n); c = mb_ptr2char(p + n); - tl = mb_cptr2len(p + n); + tl = MB_CPTR2LEN(p + n); memmove(p + tl, p, n); mb_char2bytes(c, p); stack[depth].ts_fidxtry = sp->ts_fidx + n + tl; @@ -4980,8 +4980,8 @@ static void find_keepcap_word(slang_T *slang, char_u *fword, char_u *kword) // round[depth] == 1: Try using the folded-case character. // round[depth] == 2: Try using the upper-case character. if (has_mbyte) { - flen = mb_cptr2len(fword + fwordidx[depth]); - ulen = mb_cptr2len(uword + uwordidx[depth]); + flen = MB_CPTR2LEN(fword + fwordidx[depth]); + ulen = MB_CPTR2LEN(uword + uwordidx[depth]); } else ulen = flen = 1; if (round[depth] == 1) { diff --git a/src/nvim/testdir/test_alot.vim b/src/nvim/testdir/test_alot.vim index 3da9b82a9f..3d3aa3449e 100644 --- a/src/nvim/testdir/test_alot.vim +++ b/src/nvim/testdir/test_alot.vim @@ -21,6 +21,7 @@ source test_options.vim source test_partial.vim source test_popup.vim source test_regexp_utf8.vim +source test_source_utf8.vim source test_statusline.vim source test_syn_attr.vim source test_tabline.vim diff --git a/src/nvim/testdir/test_regexp_utf8.vim b/src/nvim/testdir/test_regexp_utf8.vim index ecc7ed3e53..9e9a3de500 100644 --- a/src/nvim/testdir/test_regexp_utf8.vim +++ b/src/nvim/testdir/test_regexp_utf8.vim @@ -90,21 +90,6 @@ func Test_classes_re2() set re=0 endfunc -func Test_source_utf8() - " check that sourcing a script with 0x80 as second byte works - new - call setline(1, [':%s/àx/--à1234--/g', ':%s/Àx/--À1234--/g']) - write! Xscript - bwipe! - new - call setline(1, [' àx ', ' Àx ']) - source! Xscript | echo - call assert_equal(' --à1234-- ', getline(1)) - call assert_equal(' --À1234-- ', getline(2)) - bwipe! - call delete('Xscript') -endfunc - func Test_recursive_substitute() new s/^/\=execute("s#^##gn") diff --git a/src/nvim/testdir/test_source_utf8.vim b/src/nvim/testdir/test_source_utf8.vim new file mode 100644 index 0000000000..edb76fc43d --- /dev/null +++ b/src/nvim/testdir/test_source_utf8.vim @@ -0,0 +1,33 @@ +" Test the :source! command +if !has('multi_byte') + finish +endif + +func Test_source_utf8() + " check that sourcing a script with 0x80 as second byte works + new + call setline(1, [':%s/àx/--à1234--/g', ':%s/Àx/--À1234--/g']) + write! Xscript + bwipe! + new + call setline(1, [' àx ', ' Àx ']) + source! Xscript | echo + call assert_equal(' --à1234-- ', getline(1)) + call assert_equal(' --À1234-- ', getline(2)) + bwipe! + call delete('Xscript') +endfunc + +func Test_source_latin() + " check that sourcing a latin1 script with a 0xc0 byte works + new + call setline(1, ["call feedkeys('r')", "call feedkeys('\xc0', 'xt')"]) + write! Xscript + bwipe! + new + call setline(1, ['xxx']) + source Xscript + call assert_equal("\u00c0xx", getline(1)) + bwipe! + call delete('Xscript') +endfunc diff --git a/src/nvim/version.c b/src/nvim/version.c index 8e8072bf29..0ed6137d35 100644 --- a/src/nvim/version.c +++ b/src/nvim/version.c @@ -217,7 +217,7 @@ static int included_patches[] = { 2226, 2225, // 2224, - // 2223, + 2223, 2222, // 2221, 2220, |