Skip to content

Commit 489d609

Browse files
gpandersbrammool
authored andcommitted
patch 8.2.3362: buffer overflow when completing long tag name
Problem: Buffer overflow when completing long tag name. Solution: Allocate the buffer dynamically. (Gregory Anders, closes #8769)
1 parent d895b1d commit 489d609

File tree

3 files changed

+51
-16
lines changed

3 files changed

+51
-16
lines changed

src/tag.c

Lines changed: 39 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -3878,42 +3878,65 @@ expand_tags(
38783878
char_u ***file)
38793879
{
38803880
int i;
3881-
int c;
3882-
int tagnmflag;
3883-
char_u tagnm[100];
3881+
int extra_flag;
3882+
char_u *name_buf;
3883+
size_t name_buf_size = 100;
38843884
tagptrs_T t_p;
38853885
int ret;
38863886

3887+
name_buf = alloc(name_buf_size);
3888+
if (name_buf == NULL)
3889+
return FAIL;
3890+
38873891
if (tagnames)
3888-
tagnmflag = TAG_NAMES;
3892+
extra_flag = TAG_NAMES;
38893893
else
3890-
tagnmflag = 0;
3894+
extra_flag = 0;
38913895
if (pat[0] == '/')
38923896
ret = find_tags(pat + 1, num_file, file,
3893-
TAG_REGEXP | tagnmflag | TAG_VERBOSE | TAG_NO_TAGFUNC,
3897+
TAG_REGEXP | extra_flag | TAG_VERBOSE | TAG_NO_TAGFUNC,
38943898
TAG_MANY, curbuf->b_ffname);
38953899
else
38963900
ret = find_tags(pat, num_file, file,
3897-
TAG_REGEXP | tagnmflag | TAG_VERBOSE | TAG_NO_TAGFUNC | TAG_NOIC,
3901+
TAG_REGEXP | extra_flag | TAG_VERBOSE | TAG_NO_TAGFUNC | TAG_NOIC,
38983902
TAG_MANY, curbuf->b_ffname);
38993903
if (ret == OK && !tagnames)
39003904
{
39013905
// Reorganize the tags for display and matching as strings of:
39023906
// "<tagname>\0<kind>\0<filename>\0"
39033907
for (i = 0; i < *num_file; i++)
39043908
{
3909+
size_t len;
3910+
39053911
parse_match((*file)[i], &t_p);
3906-
c = (int)(t_p.tagname_end - t_p.tagname);
3907-
mch_memmove(tagnm, t_p.tagname, (size_t)c);
3908-
tagnm[c++] = 0;
3909-
tagnm[c++] = (t_p.tagkind != NULL && *t_p.tagkind)
3910-
? *t_p.tagkind : 'f';
3911-
tagnm[c++] = 0;
3912-
mch_memmove((*file)[i] + c, t_p.fname, t_p.fname_end - t_p.fname);
3913-
(*file)[i][c + (t_p.fname_end - t_p.fname)] = 0;
3914-
mch_memmove((*file)[i], tagnm, (size_t)c);
3912+
len = t_p.tagname_end - t_p.tagname;
3913+
if (len > name_buf_size - 3)
3914+
{
3915+
char_u *buf;
3916+
3917+
name_buf_size = len + 3;
3918+
buf = vim_realloc(name_buf, name_buf_size);
3919+
if (buf == NULL)
3920+
{
3921+
vim_free(name_buf);
3922+
return FAIL;
3923+
}
3924+
name_buf = buf;
3925+
}
3926+
3927+
mch_memmove(name_buf, t_p.tagname, len);
3928+
name_buf[len++] = 0;
3929+
name_buf[len++] = (t_p.tagkind != NULL && *t_p.tagkind)
3930+
? *t_p.tagkind : 'f';
3931+
name_buf[len++] = 0;
3932+
mch_memmove((*file)[i] + len, t_p.fname,
3933+
t_p.fname_end - t_p.fname);
3934+
(*file)[i][len + (t_p.fname_end - t_p.fname)] = 0;
3935+
mch_memmove((*file)[i], name_buf, len);
39153936
}
39163937
}
3938+
3939+
vim_free(name_buf);
39173940
return ret;
39183941
}
39193942

src/testdir/test_tagjump.vim

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -606,6 +606,16 @@ func Test_tag_line_toolong()
606606
call assert_equal('Xsomewhere', expand('%'))
607607
call assert_equal(3, getcurpos()[1])
608608

609+
" expansion on command line works with long lines when &wildoptions contains
610+
" 'tagfile'
611+
set wildoptions=tagfile
612+
call writefile([
613+
\ 'aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa file /^pattern$/;" f'
614+
\ ], 'Xtags')
615+
call feedkeys(":tag \<Tab>", 'tx')
616+
" Should not crash
617+
call assert_true(v:true)
618+
609619
call delete('Xtags')
610620
call delete('Xsomewhere')
611621
set tags&

src/version.c

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -755,6 +755,8 @@ static char *(features[]) =
755755

756756
static int included_patches[] =
757757
{ /* Add new patch number below this line */
758+
/**/
759+
3362,
758760
/**/
759761
3361,
760762
/**/

0 commit comments

Comments
 (0)