Patch 8.2.3362
Problem: Buffer overflow when completing long tag name.
Solution: Allocate the buffer dynamically. (Gregory Anders, closes #8769)
Files: src/tag.c, src/testdir/test_tagjump.vim
*** ../vim-8.2.3361/src/tag.c 2021-08-11 17:01:41.614253926 +0200
--- src/tag.c 2021-08-21 16:19:03.838782152 +0200
***************
*** 3878,3900 ****
char_u ***file)
{
int i;
! int c;
! int tagnmflag;
! char_u tagnm[100];
tagptrs_T t_p;
int ret;
if (tagnames)
! tagnmflag = TAG_NAMES;
else
! tagnmflag = 0;
if (pat[0] == '/')
ret = find_tags(pat + 1, num_file, file,
! TAG_REGEXP | tagnmflag | TAG_VERBOSE | TAG_NO_TAGFUNC,
TAG_MANY, curbuf->b_ffname);
else
ret = find_tags(pat, num_file, file,
! TAG_REGEXP | tagnmflag | TAG_VERBOSE | TAG_NO_TAGFUNC | TAG_NOIC,
TAG_MANY, curbuf->b_ffname);
if (ret == OK && !tagnames)
{
--- 3878,3904 ----
char_u ***file)
{
int i;
! int extra_flag;
! char_u *name_buf;
! size_t name_buf_size = 100;
tagptrs_T t_p;
int ret;
+ name_buf = alloc(name_buf_size);
+ if (name_buf == NULL)
+ return FAIL;
+
if (tagnames)
! extra_flag = TAG_NAMES;
else
! extra_flag = 0;
if (pat[0] == '/')
ret = find_tags(pat + 1, num_file, file,
! TAG_REGEXP | extra_flag | TAG_VERBOSE | TAG_NO_TAGFUNC,
TAG_MANY, curbuf->b_ffname);
else
ret = find_tags(pat, num_file, file,
! TAG_REGEXP | extra_flag | TAG_VERBOSE | TAG_NO_TAGFUNC | TAG_NOIC,
TAG_MANY, curbuf->b_ffname);
if (ret == OK && !tagnames)
{
***************
*** 3902,3919 ****
// "<tagname>\0<kind>\0<filename>\0"
for (i = 0; i < *num_file; i++)
{
parse_match((*file)[i], &t_p);
! c = (int)(t_p.tagname_end - t_p.tagname);
! mch_memmove(tagnm, t_p.tagname, (size_t)c);
! tagnm[c++] = 0;
! tagnm[c++] = (t_p.tagkind != NULL && *t_p.tagkind)
! ? *t_p.tagkind : 'f';
! tagnm[c++] = 0;
! mch_memmove((*file)[i] + c, t_p.fname, t_p.fname_end - t_p.fname);
! (*file)[i][c + (t_p.fname_end - t_p.fname)] = 0;
! mch_memmove((*file)[i], tagnm, (size_t)c);
}
}
return ret;
}
--- 3906,3942 ----
// "<tagname>\0<kind>\0<filename>\0"
for (i = 0; i < *num_file; i++)
{
+ size_t len;
+
parse_match((*file)[i], &t_p);
! len = t_p.tagname_end - t_p.tagname;
! if (len > name_buf_size - 3)
! {
! char_u *buf;
!
! name_buf_size = len + 3;
! buf = vim_realloc(name_buf, name_buf_size);
! if (buf == NULL)
! {
! vim_free(name_buf);
! return FAIL;
! }
! name_buf = buf;
! }
!
! mch_memmove(name_buf, t_p.tagname, len);
! name_buf[len++] = 0;
! name_buf[len++] = (t_p.tagkind != NULL && *t_p.tagkind)
! ? *t_p.tagkind : 'f';
! name_buf[len++] = 0;
! mch_memmove((*file)[i] + len, t_p.fname,
! t_p.fname_end - t_p.fname);
! (*file)[i][len + (t_p.fname_end - t_p.fname)] = 0;
! mch_memmove((*file)[i], name_buf, len);
}
}
+
+ vim_free(name_buf);
return ret;
}
*** ../vim-8.2.3361/src/testdir/test_tagjump.vim 2021-06-19 20:45:07.353511358 +0200
--- src/testdir/test_tagjump.vim 2021-08-21 16:12:21.435785981 +0200
***************
*** 606,611 ****
--- 606,621 ----
call assert_equal('Xsomewhere', expand('%'))
call assert_equal(3, getcurpos()[1])
+ " expansion on command line works with long lines when &wildoptions contains
+ " 'tagfile'
+ set wildoptions=tagfile
+ call writefile([
+ \ 'aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa file /^pattern$/;" f'
+ \ ], 'Xtags')
+ call feedkeys(":tag \<Tab>", 'tx')
+ " Should not crash
+ call assert_true(v:true)
+
call delete('Xtags')
call delete('Xsomewhere')
set tags&
*** ../vim-8.2.3361/src/version.c 2021-08-20 20:54:20.558119674 +0200
--- src/version.c 2021-08-21 16:20:47.750522640 +0200
***************
*** 757,758 ****
--- 757,760 ----
{ /* Add new patch number below this line */
+ /**/
+ 3362,
/**/
--
A law to reduce crime states: "It is mandatory for a motorist with criminal
intentions to stop at the city limits and telephone the chief of police as he
is entering the town.
[real standing law in Washington, United States of America]
/// Bram Moolenaar -- Br...@Moolenaar.net --
http://www.Moolenaar.net \\\
/// \\\
\\\ sponsor Vim, vote for features --
http://www.Vim.org/sponsor/ ///
\\\ help me help AIDS victims --
http://ICCF-Holland.org ///