diff options
author | Gregory Anders <greg@gpanders.com> | 2021-08-25 19:57:18 -0600 |
---|---|---|
committer | GitHub <noreply@github.com> | 2021-08-25 21:57:18 -0400 |
commit | 8d62f5fd58d421edb39b66fd8b350325120b3cd6 (patch) | |
tree | 0bd845b910298f13868a9d8e4ffac7a6d143bb64 | |
parent | 10d7d73b2dc6db081a8a1f405204d35cccb85196 (diff) | |
download | rneovim-8d62f5fd58d421edb39b66fd8b350325120b3cd6.tar.gz rneovim-8d62f5fd58d421edb39b66fd8b350325120b3cd6.tar.bz2 rneovim-8d62f5fd58d421edb39b66fd8b350325120b3cd6.zip |
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)
https://github.com/vim/vim/commit/489d60996deb5e7c1a3b4633412d54632e6def42
-rw-r--r-- | src/nvim/tag.c | 51 | ||||
-rw-r--r-- | src/nvim/testdir/test_tagjump.vim | 10 |
2 files changed, 42 insertions, 19 deletions
diff --git a/src/nvim/tag.c b/src/nvim/tag.c index a971849f4c..61d48eb4bf 100644 --- a/src/nvim/tag.c +++ b/src/nvim/tag.c @@ -3061,24 +3061,26 @@ expand_tags ( ) { int i; - int c; - int tagnmflag; - char_u tagnm[100]; + int extra_flag; + char_u *name_buf; + size_t name_buf_size = 100; tagptrs_T t_p; int ret; - if (tagnames) - tagnmflag = TAG_NAMES; - else - tagnmflag = 0; + name_buf = xmalloc(name_buf_size); + + if (tagnames) { + extra_flag = TAG_NAMES; + } else { + extra_flag = 0; + } if (pat[0] == '/') { 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); } else { ret = find_tags(pat, num_file, file, - TAG_REGEXP | tagnmflag | TAG_VERBOSE - | TAG_NO_TAGFUNC | TAG_NOIC, + TAG_REGEXP | extra_flag | TAG_VERBOSE | TAG_NO_TAGFUNC | TAG_NOIC, TAG_MANY, curbuf->b_ffname); } if (ret == OK && !tagnames) { @@ -3086,18 +3088,29 @@ expand_tags ( * "<tagname>\0<kind>\0<filename>\0" */ for (i = 0; i < *num_file; i++) { + size_t len; + parse_match((*file)[i], &t_p); - c = (int)(t_p.tagname_end - t_p.tagname); - 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; - 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; - memmove((*file)[i], tagnm, (size_t)c); + len = t_p.tagname_end - t_p.tagname; + if (len > name_buf_size - 3) { + char_u *buf; + + name_buf_size = len + 3; + buf = xrealloc(name_buf, name_buf_size); + name_buf = buf; + } + + 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; } diff --git a/src/nvim/testdir/test_tagjump.vim b/src/nvim/testdir/test_tagjump.vim index b6d9143bc9..0fa7f85f0d 100644 --- a/src/nvim/testdir/test_tagjump.vim +++ b/src/nvim/testdir/test_tagjump.vim @@ -548,6 +548,16 @@ func Test_tag_line_toolong() 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& |