aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJames McCoy <jamessan@jamessan.com>2017-03-10 17:26:22 -0500
committerJames McCoy <jamessan@jamessan.com>2017-03-11 20:32:38 -0500
commit2ed2b1d505cc028347b579f677eb8e6bde9dacdd (patch)
tree90636600427eae51716a16beb659fe7dd8cb2192
parenteaf1f9b9dc62b2201fa54374a88029de1b3f94fb (diff)
downloadrneovim-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.c6
-rw-r--r--src/nvim/getchar.c19
-rw-r--r--src/nvim/macros.h2
-rw-r--r--src/nvim/spell.c22
-rw-r--r--src/nvim/testdir/test_alot.vim1
-rw-r--r--src/nvim/testdir/test_regexp_utf8.vim15
-rw-r--r--src/nvim/testdir/test_source_utf8.vim33
-rw-r--r--src/nvim/version.c2
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,