]> granicus.if.org Git - vim/commitdiff
patch 7.4.2223 v7.4.2223
authorBram Moolenaar <Bram@vim.org>
Wed, 17 Aug 2016 19:32:09 +0000 (21:32 +0200)
committerBram Moolenaar <Bram@vim.org>
Wed, 17 Aug 2016 19:32:09 +0000 (21:32 +0200)
Problem:    Buffer overflow when using latin1 character with feedkeys().
Solution:   Check for an illegal character.  Add a test.

src/Makefile
src/evalfunc.c
src/getchar.c
src/macros.h
src/os_unix.c
src/os_win32.c
src/spell.c
src/testdir/test_alot_utf8.vim
src/testdir/test_regexp_utf8.vim
src/testdir/test_source_utf8.vim [new file with mode: 0644]
src/version.c

index 84ebdc61da1ae9d2d80139e5eaa7551197ade4b6..28b4b20fd08bbc08ed9ee646c9f1e496547854ed 100644 (file)
@@ -2114,6 +2114,7 @@ test_arglist \
        test_set \
        test_signs \
        test_sort \
+       test_source_utf8 \
        test_startup \
        test_startup_utf8 \
        test_stat \
index cc38d94c98e794820d6c33ff24142d631aae4a93..b427ecf7e1cc4b3b739a14e2d465b325749917c9 100644 (file)
@@ -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;
            }
        }
index 1c170cc435a50b7dee7cbb4fc0580e0a3a37ba43..52b1853776d447128ab226d47a26153a988db738 100644 (file)
@@ -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;
index ae784d6cc1a1e4ae3da7754d343ffb3b62e386ac..28f43a3627873ab0f4263636c065918b7c59a7f3 100644 (file)
 /* 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))
 # 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
index 78063704cab1e722b091101c6e3a6566c340e791..d5c5d846bb2019bba7172ac1afeaf2e84760950a 100644 (file)
@@ -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)
index d502634e3e1b5b8ca7ee07c987fb55519547a059..97a8cca9ebb5dbabe0a6608e0cedc1a4f40e8009 100644 (file)
@@ -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)
index 35235e04be39aa34aee59cbb09f9835ac7eaff2f..8d8689ba2a98dfa597b855b9df3f98702fc6bba4 100644 (file)
@@ -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
index 049251f9a76c12a7cc096d1c1328c4a4f82e9384..539e0e1e43843af55858a0ec3afed870d967ec49 100644 (file)
@@ -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
index ea918291629575fd4959a6fc3fc8c64be377998d..d2259835ca44d10e46eba1d1ce3f1cb138a153fd 100644 (file)
@@ -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 (file)
index 0000000..edb76fc
--- /dev/null
@@ -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
index 539685dde0a9aa63836de9680de880697fb43be8..a6c0ae3994ec49824150816364f3be204f2fdcdc 100644 (file)
@@ -763,6 +763,8 @@ static char *(features[]) =
 
 static int included_patches[] =
 {   /* Add new patch number below this line */
+/**/
+    2223,
 /**/
     2222,
 /**/