]> granicus.if.org Git - vim/commitdiff
patch 8.2.3362: buffer overflow when completing long tag name v8.2.3362
authorGregory Anders <greg@gpanders.com>
Sat, 21 Aug 2021 14:21:19 +0000 (16:21 +0200)
committerBram Moolenaar <Bram@vim.org>
Sat, 21 Aug 2021 14:21:19 +0000 (16:21 +0200)
Problem:    Buffer overflow when completing long tag name.
Solution:   Allocate the buffer dynamically. (Gregory Anders, closes #8769)

src/tag.c
src/testdir/test_tagjump.vim
src/version.c

index d729c4621a2c6da878765683bf49ee187fe9ce42..2e57095ba5c44ef31ede9941aeb5731cfb339320 100644 (file)
--- 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;
 }
 
index 92af0d0b0fbbd1ed8d425a5f64d52c3ab5b74168..ba55159c7a4a9afa9f836cb634e52bb83926f1b4 100644 (file)
@@ -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&
index e064df3e7b590ec5c7e4c11b3c33d18f064577dc..dfe949d9d0428fc5369abad29c2b2d0a29cb8a54 100644 (file)
@@ -755,6 +755,8 @@ static char *(features[]) =
 
 static int included_patches[] =
 {   /* Add new patch number below this line */
+/**/
+    3362,
 /**/
     3361,
 /**/