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.