]> granicus.if.org Git - vim/commitdiff
patch 8.0.1218: writing to freed memory in autocmd v8.0.1218
authorBram Moolenaar <Bram@vim.org>
Thu, 26 Oct 2017 14:42:16 +0000 (16:42 +0200)
committerBram Moolenaar <Bram@vim.org>
Thu, 26 Oct 2017 14:42:16 +0000 (16:42 +0200)
Problem:    Writing to freed memory in autocmd.
Solution:   Make a copy of the tag line. (Dominique Pelle, closes #2245)

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

index e39098843f41240dd8c3e3f1b049f594d50c4cfd..0233822c1d0303754f10f69db226ab4c668d046c 100644 (file)
--- a/src/tag.c
+++ b/src/tag.c
@@ -2949,6 +2949,25 @@ test_for_static(tagptrs_T *tagp)
     return FALSE;
 }
 
+/*
+ * Returns the length of a matching tag line.
+ */
+    static size_t
+matching_line_len(char_u *lbuf)
+{
+    char_u     *p = lbuf + 1;
+
+    /* does the same thing as parse_match() */
+    p += STRLEN(p) + 2;
+#ifdef FEAT_EMACS_TAGS
+    if (*p)
+       p += STRLEN(p);
+    else
+       ++p;
+#endif
+    return (p - lbuf) + STRLEN(p);
+}
+
 /*
  * Parse a line from a matching tag.  Does not change the line itself.
  *
@@ -3071,7 +3090,7 @@ tag_full_fname(tagptrs_T *tagp)
  */
     static int
 jumpto_tag(
-    char_u     *lbuf,          /* line from the tags file for this tag */
+    char_u     *lbuf_arg,      /* line from the tags file for this tag */
     int                forceit,        /* :ta with ! */
     int                keep_help)      /* keep help flag (FALSE for cscope) */
 {
@@ -3079,7 +3098,6 @@ jumpto_tag(
     int                save_magic;
     int                save_p_ws, save_p_scs, save_p_ic;
     linenr_T   save_lnum;
-    int                csave = 0;
     char_u     *str;
     char_u     *pbuf;                  /* search pattern buffer */
     char_u     *pbuf_end;
@@ -3099,18 +3117,26 @@ jumpto_tag(
 #ifdef FEAT_FOLDING
     int                old_KeyTyped = KeyTyped;    /* getting the file may reset it */
 #endif
+    size_t     len;
+    char_u     *lbuf;
+
+    /* Make a copy of the line, it can become invalid when an autocommand calls
+     * back here recursively. */
+    len = matching_line_len(lbuf_arg) + 1;
+    lbuf = alloc((int)len);
+    if (lbuf != NULL)
+       mch_memmove(lbuf, lbuf_arg, len);
 
     pbuf = alloc(LSIZE);
 
     /* parse the match line into the tagp structure */
-    if (pbuf == NULL || parse_match(lbuf, &tagp) == FAIL)
+    if (pbuf == NULL || lbuf == NULL || parse_match(lbuf, &tagp) == FAIL)
     {
        tagp.fname_end = NULL;
        goto erret;
     }
 
     /* truncate the file name, so it can be used as a string */
-    csave = *tagp.fname_end;
     *tagp.fname_end = NUL;
     fname = tagp.fname;
 
@@ -3246,7 +3272,10 @@ jumpto_tag(
 #endif
            keep_help_flag = curbuf->b_help;
     }
+
     if (getfile_result == GETFILE_UNUSED)
+       /* Careful: getfile() may trigger autocommands and call jumpto_tag()
+        * recursively. */
        getfile_result = getfile(0, fname, NULL, TRUE, (linenr_T)0, forceit);
     keep_help_flag = FALSE;
 
@@ -3441,8 +3470,7 @@ erret:
 #if defined(FEAT_QUICKFIX)
     g_do_tagpreview = 0; /* For next time */
 #endif
-    if (tagp.fname_end != NULL)
-       *tagp.fname_end = csave;
+    vim_free(lbuf);
     vim_free(pbuf);
     vim_free(tofree_fname);
     vim_free(full_fname);
index 6ca3b220e616cd3b0a06aac7936bd8c1d33ef66f..aa7d15779914909406e2bc093c86df0548e78569 100644 (file)
@@ -249,6 +249,24 @@ func Test_augroup_warning()
   au! VimEnter
 endfunc
 
+func Test_BufReadCmdHelp()
+  " This used to cause access to free memory
+  au BufReadCmd * e +h
+  help
+
+  helpclose
+  au! BufReadCmd
+endfunc
+
+func Test_BufReadCmdHelpJump()
+  " This used to cause access to free memory
+  au BufReadCmd * e +h{
+  help
+
+  helpclose
+  au! BufReadCmd
+endfunc
+
 func Test_augroup_deleted()
   " This caused a crash before E936 was introduced
   augroup x
index a84c8e26ce1b27c579feea6844f9916f7dd09fe6..1c48ef4c75fb1e3df13fa1aca6f71d3ee10d5a9e 100644 (file)
@@ -761,6 +761,8 @@ static char *(features[]) =
 
 static int included_patches[] =
 {   /* Add new patch number below this line */
+/**/
+    1218,
 /**/
     1217,
 /**/