0
0
mirror of https://github.com/vim/vim.git synced 2025-09-26 04:04:07 -04:00

patch 7.4.2223

Problem:    Buffer overflow when using latin1 character with feedkeys().
Solution:   Check for an illegal character.  Add a test.
This commit is contained in:
Bram Moolenaar
2016-08-17 21:32:09 +02:00
parent 6bff02eb53
commit d3c907b5d2
11 changed files with 67 additions and 48 deletions

View File

@@ -2114,6 +2114,7 @@ test_arglist \
test_set \ test_set \
test_signs \ test_signs \
test_sort \ test_sort \
test_source_utf8 \
test_startup \ test_startup \
test_startup_utf8 \ test_startup_utf8 \
test_stat \ test_stat \

View File

@@ -11166,7 +11166,7 @@ f_strgetchar(typval_T *argvars, typval_T *rettv)
break; break;
} }
--charidx; --charidx;
byteidx += mb_cptr2len(str + byteidx); byteidx += MB_CPTR2LEN(str + byteidx);
} }
} }
#else #else
@@ -11326,7 +11326,7 @@ f_strcharpart(typval_T *argvars, typval_T *rettv)
if (nchar > 0) if (nchar > 0)
while (nchar > 0 && nbyte < slen) while (nchar > 0 && nbyte < slen)
{ {
nbyte += mb_cptr2len(p + nbyte); nbyte += MB_CPTR2LEN(p + nbyte);
--nchar; --nchar;
} }
else else
@@ -11341,7 +11341,7 @@ f_strcharpart(typval_T *argvars, typval_T *rettv)
if (off < 0) if (off < 0)
len += 1; len += 1;
else else
len += mb_cptr2len(p + off); len += MB_CPTR2LEN(p + off);
--charlen; --charlen;
} }
} }

View File

@@ -4658,8 +4658,16 @@ vim_strsave_escape_csi(
char_u *res; char_u *res;
char_u *s, *d; char_u *s, *d;
/* Need a buffer to hold up to three times as much. */ /* Need a buffer to hold up to three times as much. Four in case of an
res = alloc((unsigned)(STRLEN(p) * 3) + 1); * 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) if (res != NULL)
{ {
d = res; d = res;
@@ -4674,22 +4682,10 @@ vim_strsave_escape_csi(
} }
else else
{ {
#ifdef FEAT_MBYTE
int len = mb_char2len(PTR2CHAR(s));
int len2 = mb_ptr2len(s);
#endif
/* Add character, possibly multi-byte to destination, escaping /* 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); d = add_char2buf(PTR2CHAR(s), d);
#ifdef FEAT_MBYTE s += MB_CPTR2LEN(s);
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);
} }
} }
*d = NUL; *d = NUL;

View File

@@ -274,7 +274,7 @@
/* Backup multi-byte pointer. Only use with "p" > "s" ! */ /* 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 # 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 */ /* 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_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)) # 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)) # define PTR2CHAR(p) (has_mbyte ? mb_ptr2char(p) : (int)*(p))
#else #else
# define MB_PTR2LEN(p) 1 # define MB_PTR2LEN(p) 1
# define MB_CPTR2LEN(p) 1
# define mb_ptr_adv(p) ++p # define mb_ptr_adv(p) ++p
# define mb_cptr_adv(p) ++p # define mb_cptr_adv(p) ++p
# define mb_ptr_back(s, p) --p # define mb_ptr_back(s, p) --p

View File

@@ -4806,7 +4806,7 @@ mch_call_shell(
* round. */ * round. */
for (p = buffer; p < buffer + len; p += l) for (p = buffer; p < buffer + len; p += l)
{ {
l = mb_cptr2len(p); l = MB_CPTR2LEN(p);
if (l == 0) if (l == 0)
l = 1; /* NUL byte? */ l = 1; /* NUL byte? */
else if (MB_BYTE2LEN(*p) != l) else if (MB_BYTE2LEN(*p) != l)

View File

@@ -4370,7 +4370,7 @@ dump_pipe(int options,
* round. */ * round. */
for (p = buffer; p < buffer + len; p += l) for (p = buffer; p < buffer + len; p += l)
{ {
l = mb_cptr2len(p); l = MB_CPTR2LEN(p);
if (l == 0) if (l == 0)
l = 1; /* NUL byte? */ l = 1; /* NUL byte? */
else if (MB_BYTE2LEN(*p) != l) else if (MB_BYTE2LEN(*p) != l)

View File

@@ -5379,7 +5379,7 @@ suggest_trie_walk(
#ifdef FEAT_MBYTE #ifdef FEAT_MBYTE
if (has_mbyte) if (has_mbyte)
{ {
n = mb_cptr2len(p); n = MB_CPTR2LEN(p);
c = mb_ptr2char(p); c = mb_ptr2char(p);
if (p[n] == NUL) if (p[n] == NUL)
c2 = NUL; c2 = NUL;
@@ -5477,9 +5477,9 @@ suggest_trie_walk(
#ifdef FEAT_MBYTE #ifdef FEAT_MBYTE
if (has_mbyte) if (has_mbyte)
{ {
n = mb_cptr2len(p); n = MB_CPTR2LEN(p);
c = mb_ptr2char(p); c = mb_ptr2char(p);
fl = mb_cptr2len(p + n); fl = MB_CPTR2LEN(p + n);
c2 = mb_ptr2char(p + n); c2 = mb_ptr2char(p + n);
if (!soundfold && !spell_iswordp(p + n + fl, curwin)) if (!soundfold && !spell_iswordp(p + n + fl, curwin))
c3 = c; /* don't swap non-word char */ c3 = c; /* don't swap non-word char */
@@ -5596,10 +5596,10 @@ suggest_trie_walk(
#ifdef FEAT_MBYTE #ifdef FEAT_MBYTE
if (has_mbyte) if (has_mbyte)
{ {
n = mb_cptr2len(p); n = MB_CPTR2LEN(p);
c = mb_ptr2char(p); c = mb_ptr2char(p);
fl = mb_cptr2len(p + n); fl = MB_CPTR2LEN(p + n);
fl += mb_cptr2len(p + n + fl); fl += MB_CPTR2LEN(p + n + fl);
mch_memmove(p, p + n, fl); mch_memmove(p, p + n, fl);
mb_char2bytes(c, p + fl); mb_char2bytes(c, p + fl);
stack[depth].ts_fidxtry = sp->ts_fidx + n + fl; stack[depth].ts_fidxtry = sp->ts_fidx + n + fl;
@@ -5661,10 +5661,10 @@ suggest_trie_walk(
#ifdef FEAT_MBYTE #ifdef FEAT_MBYTE
if (has_mbyte) if (has_mbyte)
{ {
n = mb_cptr2len(p); n = MB_CPTR2LEN(p);
n += mb_cptr2len(p + n); n += MB_CPTR2LEN(p + n);
c = mb_ptr2char(p + n); c = mb_ptr2char(p + n);
tl = mb_cptr2len(p + n); tl = MB_CPTR2LEN(p + n);
mch_memmove(p + tl, p, n); mch_memmove(p + tl, p, n);
mb_char2bytes(c, p); mb_char2bytes(c, p);
stack[depth].ts_fidxtry = sp->ts_fidx + n + tl; 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 #ifdef FEAT_MBYTE
if (has_mbyte) if (has_mbyte)
{ {
flen = mb_cptr2len(fword + fwordidx[depth]); flen = MB_CPTR2LEN(fword + fwordidx[depth]);
ulen = mb_cptr2len(uword + uwordidx[depth]); ulen = MB_CPTR2LEN(uword + uwordidx[depth]);
} }
else else
#endif #endif

View File

@@ -8,3 +8,4 @@
source test_expr_utf8.vim source test_expr_utf8.vim
source test_matchadd_conceal_utf8.vim source test_matchadd_conceal_utf8.vim
source test_regexp_utf8.vim source test_regexp_utf8.vim
source test_source_utf8.vim

View File

@@ -92,18 +92,3 @@ func Test_classes_re2()
call s:classes_test() call s:classes_test()
set re=0 set re=0
endfunc 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

View File

@@ -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

View File

@@ -763,6 +763,8 @@ static char *(features[]) =
static int included_patches[] = static int included_patches[] =
{ /* Add new patch number below this line */ { /* Add new patch number below this line */
/**/
2223,
/**/ /**/
2222, 2222,
/**/ /**/