Mercurial > vim
changeset 25652:ca61340ac1b9 v8.2.3362
patch 8.2.3362: buffer overflow when completing long tag name
Commit: https://github.com/vim/vim/commit/489d60996deb5e7c1a3b4633412d54632e6def42
Author: Gregory Anders <greg@gpanders.com>
Date: Sat Aug 21 16:21:19 2021 +0200
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 https://github.com/vim/vim/issues/8769)
author | Bram Moolenaar <Bram@vim.org> |
---|---|
date | Sat, 21 Aug 2021 16:30:04 +0200 |
parents | 3066656a3860 |
children | dc3b761cc059 |
files | src/tag.c src/testdir/test_tagjump.vim src/version.c |
diffstat | 3 files changed, 51 insertions(+), 16 deletions(-) [+] |
line wrap: on
line diff
--- a/src/tag.c +++ b/src/tag.c @@ -3878,23 +3878,27 @@ expand_tags( char_u ***file) { 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; + name_buf = alloc(name_buf_size); + if (name_buf == NULL) + return FAIL; + if (tagnames) - tagnmflag = TAG_NAMES; + extra_flag = TAG_NAMES; else - tagnmflag = 0; + 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) { @@ -3902,18 +3906,37 @@ 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); - 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); + 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; }
--- a/src/testdir/test_tagjump.vim +++ b/src/testdir/test_tagjump.vim @@ -606,6 +606,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&