Dominique wrote:

> Valgrind shows a write beyond end of string
> in Vim-7.4.2222 (huge) and older when doing:
> 
> $ vim -u NONE -N -S bug-feedkeys-7.4.7222.vim 2> log
> 
> ... where bug-feedkeys-7.4.7222.vim is the one-line
> attached file. Note that the file is in latin1 encoding
> and my locale is en_US.UTF-8.
> 
> log file contains:
> 
> ==4157== Memcheck, a memory error detector
> ==4157== Copyright (C) 2002-2015, and GNU GPL'd, by Julian Seward et al.
> ==4157== Using Valgrind-3.12.0.SVN and LibVEX; rerun with -h for copyright 
> info
> ==4157== Command: vim -u NONE -N -S bug-feedkeys-7.4.7222.vim
> ==4157==
> ==4157== Invalid write of size 1
> ==4157==    at 0x4BB05F: vim_strsave_escape_csi (getchar.c:4695)
> ==4157==    by 0x44DE8C: f_feedkeys (evalfunc.c:3126)
> ==4157==    by 0x44A339: call_internal_func (evalfunc.c:997)
> ==4157==    by 0x5E53E6: call_func (userfunc.c:1372)
> ==4157==    by 0x5E319D: get_func_tv (userfunc.c:455)
> ==4157==    by 0x5E8F70: ex_call (userfunc.c:2981)
> ==4157==    by 0x47AC68: do_one_cmd (ex_docmd.c:2925)
> ==4157==    by 0x477954: do_cmdline (ex_docmd.c:1110)
> ==4157==    by 0x4755F8: do_source (ex_cmds2.c:4084)
> ==4157==    by 0x474C0A: cmd_source (ex_cmds2.c:3697)
> ==4157==    by 0x474B58: ex_source (ex_cmds2.c:3672)
> ==4157==    by 0x47AC68: do_one_cmd (ex_docmd.c:2925)
> ==4157==  Address 0xcd992d4 is 0 bytes after a block of size 4 alloc'd
> ==4157==    at 0x4C2ABF5: malloc (vg_replace_malloc.c:299)
> ==4157==    by 0x4F1427: lalloc (misc2.c:920)
> ==4157==    by 0x4F12F4: alloc (misc2.c:818)
> ==4157==    by 0x4BAE5B: vim_strsave_escape_csi (getchar.c:4662)
> ==4157==    by 0x44DE8C: f_feedkeys (evalfunc.c:3126)
> ==4157==    by 0x44A339: call_internal_func (evalfunc.c:997)
> ==4157==    by 0x5E53E6: call_func (userfunc.c:1372)
> ==4157==    by 0x5E319D: get_func_tv (userfunc.c:455)
> ==4157==    by 0x5E8F70: ex_call (userfunc.c:2981)
> ==4157==    by 0x47AC68: do_one_cmd (ex_docmd.c:2925)
> ==4157==    by 0x477954: do_cmdline (ex_docmd.c:1110)
> ==4157==    by 0x4755F8: do_source (ex_cmds2.c:4084)
> ==4157==
> ==4157== Invalid read of size 1
> ==4157==    at 0x4C2DA04: strlen (vg_replace_strmem.c:454)
> ==4157==    by 0x4B4FD2: ins_typebuf (getchar.c:979)
> ==4157==    by 0x44DEDD: f_feedkeys (evalfunc.c:3129)
> ==4157==    by 0x44A339: call_internal_func (evalfunc.c:997)
> ==4157==    by 0x5E53E6: call_func (userfunc.c:1372)
> ==4157==    by 0x5E319D: get_func_tv (userfunc.c:455)
> ==4157==    by 0x5E8F70: ex_call (userfunc.c:2981)
> ==4157==    by 0x47AC68: do_one_cmd (ex_docmd.c:2925)
> ==4157==    by 0x477954: do_cmdline (ex_docmd.c:1110)
> ==4157==    by 0x4755F8: do_source (ex_cmds2.c:4084)
> ==4157==    by 0x474C0A: cmd_source (ex_cmds2.c:3697)
> ==4157==    by 0x474B58: ex_source (ex_cmds2.c:3672)
> ==4157==  Address 0xcd992d4 is 0 bytes after a block of size 4 alloc'd
> ==4157==    at 0x4C2ABF5: malloc (vg_replace_malloc.c:299)
> ==4157==    by 0x4F1427: lalloc (misc2.c:920)
> ==4157==    by 0x4F12F4: alloc (misc2.c:818)
> ==4157==    by 0x4BAE5B: vim_strsave_escape_csi (getchar.c:4662)
> ==4157==    by 0x44DE8C: f_feedkeys (evalfunc.c:3126)
> ==4157==    by 0x44A339: call_internal_func (evalfunc.c:997)
> ==4157==    by 0x5E53E6: call_func (userfunc.c:1372)
> ==4157==    by 0x5E319D: get_func_tv (userfunc.c:455)
> ==4157==    by 0x5E8F70: ex_call (userfunc.c:2981)
> ==4157==    by 0x47AC68: do_one_cmd (ex_docmd.c:2925)
> ==4157==    by 0x477954: do_cmdline (ex_docmd.c:1110)
> ==4157==    by 0x4755F8: do_source (ex_cmds2.c:4084)
> 
> Code in getchar.c:
> 
> 4654     char_u *
> 4655 vim_strsave_escape_csi(
> 4656     char_u *p)
> 4657 {
> 4658     char_u      *res;
> 4659     char_u      *s, *d;
> 4660
> 4661     /* Need a buffer to hold up to three times as much. */
> 4662     res = alloc((unsigned)(STRLEN(p) * 3) + 1);
> 4663     if (res != NULL)
> 4664     {
> 4665         d = res;
> 4666         for (s = p; *s != NUL; )
> 4667         {
> 4668             if (s[0] == K_SPECIAL && s[1] != NUL && s[2] != NUL)
> 4669             {
> 4670                 /* Copy special key unmodified. */
> 4671                 *d++ = *s++;
> 4672                 *d++ = *s++;
> 4673                 *d++ = *s++;
> 4674             }
> 4675             else
> 4676             {
> 4677 #ifdef FEAT_MBYTE
> 4678                 int len  = mb_char2len(PTR2CHAR(s));
> 4679                 int len2 = mb_ptr2len(s);
> 4680 #endif
> 4681                 /* Add character, possibly multi-byte to
> destination, escaping
> 4682                  * CSI and K_SPECIAL. */
> 4683                 d = add_char2buf(PTR2CHAR(s), d);
> 4684 #ifdef FEAT_MBYTE
> 4685                 while (len < len2)
> 4686                 {
> 4687                     /* add following combining char */
> 4688                     d = add_char2buf(PTR2CHAR(s + len), d);
> 4689                     len += mb_char2len(PTR2CHAR(s + len));
> 4690                 }
> 4691 #endif
> 4692                 mb_ptr_adv(s);
> 4693             }
> 4694         }
> 4695         *d = NUL;
> 4696     }
> 4697     return res;
> 4698 }
> 
> I see that vim_strsave_escape_csi() is invoked with
> p[0]=0xc0 p[1]=0x0  which is a truncated utf-8 string,
> or character À in latin1.  Line 4688 calls add_char2buf(...)
> which will advance by 4 bytes, which goes beyond the
> end of buffer res (3 + 1 bytes) and then the line 4695
> writes beyond end of string.

Thanks for finding this.  With some effort I managed to make a test that
exposes this problem when run under valgrind.

> I did not write a patch as I'm confused with this code:
> I'm surprised by the comment at line 4687 which
> says /* add following combining char */.  From what I
> see, len2 does not include combining char, so the code
> does not add combining char.  In fact, it looks like we
> always have len >= len2, and so condition at line 4685
> looks always false. We have len > len2 for invalid utf8
> sequences.

It looks OK to me, len2 is obtained with mb_ptr2len() which includes
composing characters.  However, adding composing characters separately
seems pointless, they are handled the same way as base characters.

It's tricky.  I think it's OK to reserve four output bytes for each
input byte.  Please check that patch I'll send out.

-- 
How To Keep A Healthy Level Of Insanity:
16. Have your coworkers address you by your wrestling name, Rock Hard Kim.

 /// Bram Moolenaar -- b...@moolenaar.net -- http://www.Moolenaar.net   \\\
///        sponsor Vim, vote for features -- http://www.Vim.org/sponsor/ \\\
\\\  an exciting new programming language -- http://www.Zimbu.org        ///
 \\\            help me help AIDS victims -- http://ICCF-Holland.org    ///

-- 
-- 
You received this message from the "vim_dev" maillist.
Do not top-post! Type your reply below the text you are replying to.
For more information, visit http://www.vim.org/maillist.php

--- 
You received this message because you are subscribed to the Google Groups 
"vim_dev" group.
To unsubscribe from this group and stop receiving emails from it, send an email 
to vim_dev+unsubscr...@googlegroups.com.
For more options, visit https://groups.google.com/d/optout.

Raspunde prin e-mail lui