diff options
author | Bram Moolenaar <Bram@vim.org> | 2016-08-17 21:32:09 +0200 |
---|---|---|
committer | Bram Moolenaar <Bram@vim.org> | 2016-08-17 21:32:09 +0200 |
commit | d3c907b5d2b352482b580a0cf687cbbea4c19ea1 (patch) | |
tree | 4ef356217c0b95e6f6ee5b5d3bb756c103ef8b82 | |
parent | 6bff02eb530aa29aafa2cb5627399837be7a5dd5 (diff) | |
download | vim-git-d3c907b5d2b352482b580a0cf687cbbea4c19ea1.tar.gz |
patch 7.4.2223v7.4.2223
Problem: Buffer overflow when using latin1 character with feedkeys().
Solution: Check for an illegal character. Add a test.
-rw-r--r-- | src/Makefile | 1 | ||||
-rw-r--r-- | src/evalfunc.c | 6 | ||||
-rw-r--r-- | src/getchar.c | 28 | ||||
-rw-r--r-- | src/macros.h | 3 | ||||
-rw-r--r-- | src/os_unix.c | 2 | ||||
-rw-r--r-- | src/os_win32.c | 2 | ||||
-rw-r--r-- | src/spell.c | 22 | ||||
-rw-r--r-- | src/testdir/test_alot_utf8.vim | 1 | ||||
-rw-r--r-- | src/testdir/test_regexp_utf8.vim | 15 | ||||
-rw-r--r-- | src/testdir/test_source_utf8.vim | 33 | ||||
-rw-r--r-- | src/version.c | 2 |
11 files changed, 67 insertions, 48 deletions
diff --git a/src/Makefile b/src/Makefile index 84ebdc61d..28b4b20fd 100644 --- a/src/Makefile +++ b/src/Makefile @@ -2114,6 +2114,7 @@ test_arglist \ test_set \ test_signs \ test_sort \ + test_source_utf8 \ test_startup \ test_startup_utf8 \ test_stat \ diff --git a/src/evalfunc.c b/src/evalfunc.c index cc38d94c9..b427ecf7e 100644 --- a/src/evalfunc.c +++ b/src/evalfunc.c @@ -11166,7 +11166,7 @@ f_strgetchar(typval_T *argvars, typval_T *rettv) break; } --charidx; - byteidx += mb_cptr2len(str + byteidx); + byteidx += MB_CPTR2LEN(str + byteidx); } } #else @@ -11326,7 +11326,7 @@ f_strcharpart(typval_T *argvars, typval_T *rettv) if (nchar > 0) while (nchar > 0 && nbyte < slen) { - nbyte += mb_cptr2len(p + nbyte); + nbyte += MB_CPTR2LEN(p + nbyte); --nchar; } else @@ -11341,7 +11341,7 @@ f_strcharpart(typval_T *argvars, typval_T *rettv) if (off < 0) len += 1; else - len += mb_cptr2len(p + off); + len += MB_CPTR2LEN(p + off); --charlen; } } diff --git a/src/getchar.c b/src/getchar.c index 1c170cc43..52b185377 100644 --- a/src/getchar.c +++ b/src/getchar.c @@ -4658,8 +4658,16 @@ vim_strsave_escape_csi( char_u *res; char_u *s, *d; - /* Need a buffer to hold up to three times as much. */ - res = alloc((unsigned)(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 */ + res = alloc((unsigned)(STRLEN(p) * +#ifdef FEAT_MBYTE + 4 +#else + 3 +#endif + ) + 1); if (res != NULL) { d = res; @@ -4674,22 +4682,10 @@ vim_strsave_escape_csi( } else { -#ifdef FEAT_MBYTE - int len = mb_char2len(PTR2CHAR(s)); - int len2 = mb_ptr2len(s); -#endif /* Add character, possibly multi-byte to destination, escaping - * CSI and K_SPECIAL. */ + * CSI and K_SPECIAL. Be careful, it can be an illegal byte! */ d = add_char2buf(PTR2CHAR(s), d); -#ifdef FEAT_MBYTE - while (len < len2) - { - /* add following combining char */ - d = add_char2buf(PTR2CHAR(s + len), d); - len += mb_char2len(PTR2CHAR(s + len)); - } -#endif - mb_ptr_adv(s); + s += MB_CPTR2LEN(s); } } *d = NUL; diff --git a/src/macros.h b/src/macros.h index ae784d6cc..28f43a362 100644 --- a/src/macros.h +++ b/src/macros.h @@ -274,7 +274,7 @@ /* Backup multi-byte pointer. Only use with "p" > "s" ! */ # define mb_ptr_back(s, p) p -= has_mbyte ? ((*mb_head_off)(s, p - 1) + 1) : 1 /* get length of multi-byte char, not including composing chars */ -# define mb_cptr2len(p) (enc_utf8 ? utf_ptr2len(p) : (*mb_ptr2len)(p)) +# define MB_CPTR2LEN(p) (enc_utf8 ? utf_ptr2len(p) : (*mb_ptr2len)(p)) # define MB_COPY_CHAR(f, t) if (has_mbyte) mb_copy_char(&f, &t); else *t++ = *f++ # define MB_CHARLEN(p) (has_mbyte ? mb_charlen(p) : (int)STRLEN(p)) @@ -282,6 +282,7 @@ # define PTR2CHAR(p) (has_mbyte ? mb_ptr2char(p) : (int)*(p)) #else # define MB_PTR2LEN(p) 1 +# define MB_CPTR2LEN(p) 1 # define mb_ptr_adv(p) ++p # define mb_cptr_adv(p) ++p # define mb_ptr_back(s, p) --p diff --git a/src/os_unix.c b/src/os_unix.c index 78063704c..d5c5d846b 100644 --- a/src/os_unix.c +++ b/src/os_unix.c @@ -4806,7 +4806,7 @@ mch_call_shell( * round. */ for (p = buffer; p < buffer + len; p += l) { - l = mb_cptr2len(p); + l = MB_CPTR2LEN(p); if (l == 0) l = 1; /* NUL byte? */ else if (MB_BYTE2LEN(*p) != l) diff --git a/src/os_win32.c b/src/os_win32.c index d502634e3..97a8cca9e 100644 --- a/src/os_win32.c +++ b/src/os_win32.c @@ -4370,7 +4370,7 @@ dump_pipe(int options, * round. */ for (p = buffer; p < buffer + len; p += l) { - l = mb_cptr2len(p); + l = MB_CPTR2LEN(p); if (l == 0) l = 1; /* NUL byte? */ else if (MB_BYTE2LEN(*p) != l) diff --git a/src/spell.c b/src/spell.c index 35235e04b..8d8689ba2 100644 --- a/src/spell.c +++ b/src/spell.c @@ -5379,7 +5379,7 @@ suggest_trie_walk( #ifdef FEAT_MBYTE if (has_mbyte) { - n = mb_cptr2len(p); + n = MB_CPTR2LEN(p); c = mb_ptr2char(p); if (p[n] == NUL) c2 = NUL; @@ -5477,9 +5477,9 @@ suggest_trie_walk( #ifdef FEAT_MBYTE 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 */ @@ -5596,10 +5596,10 @@ suggest_trie_walk( #ifdef FEAT_MBYTE 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); mch_memmove(p, p + n, fl); mb_char2bytes(c, p + fl); stack[depth].ts_fidxtry = sp->ts_fidx + n + fl; @@ -5661,10 +5661,10 @@ suggest_trie_walk( #ifdef FEAT_MBYTE 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); mch_memmove(p + tl, p, n); mb_char2bytes(c, p); stack[depth].ts_fidxtry = sp->ts_fidx + n + tl; @@ -5955,8 +5955,8 @@ find_keepcap_word(slang_T *slang, char_u *fword, char_u *kword) #ifdef FEAT_MBYTE 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 #endif diff --git a/src/testdir/test_alot_utf8.vim b/src/testdir/test_alot_utf8.vim index 049251f9a..539e0e1e4 100644 --- a/src/testdir/test_alot_utf8.vim +++ b/src/testdir/test_alot_utf8.vim @@ -8,3 +8,4 @@ source test_expr_utf8.vim source test_matchadd_conceal_utf8.vim source test_regexp_utf8.vim +source test_source_utf8.vim diff --git a/src/testdir/test_regexp_utf8.vim b/src/testdir/test_regexp_utf8.vim index ea9182916..d2259835c 100644 --- a/src/testdir/test_regexp_utf8.vim +++ b/src/testdir/test_regexp_utf8.vim @@ -92,18 +92,3 @@ func Test_classes_re2() call s:classes_test() 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 diff --git a/src/testdir/test_source_utf8.vim b/src/testdir/test_source_utf8.vim new file mode 100644 index 000000000..edb76fc43 --- /dev/null +++ b/src/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/version.c b/src/version.c index 539685dde..a6c0ae399 100644 --- a/src/version.c +++ b/src/version.c @@ -764,6 +764,8 @@ static char *(features[]) = static int included_patches[] = { /* Add new patch number below this line */ /**/ + 2223, +/**/ 2222, /**/ 2221, |