vim-patch:8.2.3362: buffer overflow when completing long tag name (#15449)

Problem:    Buffer overflow when completing long tag name.
Solution:   Allocate the buffer dynamically. (Gregory Anders, closes vim/vim#8769)
489d60996d
This commit is contained in:
Gregory Anders 2021-08-25 19:57:18 -06:00 committed by GitHub
parent 10d7d73b2d
commit 8d62f5fd58
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
2 changed files with 42 additions and 19 deletions

View File

@ -3061,24 +3061,26 @@ expand_tags (
) )
{ {
int i; int i;
int c; int extra_flag;
int tagnmflag; char_u *name_buf;
char_u tagnm[100]; size_t name_buf_size = 100;
tagptrs_T t_p; tagptrs_T t_p;
int ret; int ret;
if (tagnames) name_buf = xmalloc(name_buf_size);
tagnmflag = TAG_NAMES;
else if (tagnames) {
tagnmflag = 0; extra_flag = TAG_NAMES;
} else {
extra_flag = 0;
}
if (pat[0] == '/') { if (pat[0] == '/') {
ret = find_tags(pat + 1, num_file, file, ret = find_tags(pat + 1, num_file, file,
TAG_REGEXP | tagnmflag | TAG_VERBOSE | TAG_NO_TAGFUNC, TAG_REGEXP | extra_flag | TAG_VERBOSE | TAG_NO_TAGFUNC,
TAG_MANY, curbuf->b_ffname); TAG_MANY, curbuf->b_ffname);
} else { } else {
ret = find_tags(pat, num_file, file, ret = find_tags(pat, num_file, file,
TAG_REGEXP | tagnmflag | TAG_VERBOSE TAG_REGEXP | extra_flag | TAG_VERBOSE | TAG_NO_TAGFUNC | TAG_NOIC,
| TAG_NO_TAGFUNC | TAG_NOIC,
TAG_MANY, curbuf->b_ffname); TAG_MANY, curbuf->b_ffname);
} }
if (ret == OK && !tagnames) { if (ret == OK && !tagnames) {
@ -3086,18 +3088,29 @@ expand_tags (
* "<tagname>\0<kind>\0<filename>\0" * "<tagname>\0<kind>\0<filename>\0"
*/ */
for (i = 0; i < *num_file; i++) { for (i = 0; i < *num_file; i++) {
size_t len;
parse_match((*file)[i], &t_p); parse_match((*file)[i], &t_p);
c = (int)(t_p.tagname_end - t_p.tagname); len = t_p.tagname_end - t_p.tagname;
memmove(tagnm, t_p.tagname, (size_t)c); if (len > name_buf_size - 3) {
tagnm[c++] = 0; char_u *buf;
tagnm[c++] = (t_p.tagkind != NULL && *t_p.tagkind)
? *t_p.tagkind : 'f'; name_buf_size = len + 3;
tagnm[c++] = 0; buf = xrealloc(name_buf, name_buf_size);
memmove((*file)[i] + c, t_p.fname, t_p.fname_end - t_p.fname); name_buf = buf;
(*file)[i][c + (t_p.fname_end - t_p.fname)] = 0; }
memmove((*file)[i], tagnm, (size_t)c);
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;
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;
memmove((*file)[i], name_buf, len);
} }
} }
xfree(name_buf);
return ret; return ret;
} }

View File

@ -548,6 +548,16 @@ func Test_tag_line_toolong()
call assert_equal('Xsomewhere', expand('%')) call assert_equal('Xsomewhere', expand('%'))
call assert_equal(3, getcurpos()[1]) 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('Xtags')
call delete('Xsomewhere') call delete('Xsomewhere')
set tags& set tags&