diff options
author | Bram Moolenaar <Bram@vim.org> | 2017-10-26 16:42:16 +0200 |
---|---|---|
committer | Bram Moolenaar <Bram@vim.org> | 2017-10-26 16:42:16 +0200 |
commit | 8d84ff1a3c8cfe59399d3f675ec080066582fdb6 (patch) | |
tree | 02286c1615353fbb090eef259ca01921aa6e84ff | |
parent | d99388ba8535a6fecf7d0bf7b982832c0b816062 (diff) |
patch 8.0.1218: writing to freed memory in autocmdv8.0.1218
Problem: Writing to freed memory in autocmd.
Solution: Make a copy of the tag line. (Dominique Pelle, closes #2245)
-rw-r--r-- | src/tag.c | 40 | ||||
-rw-r--r-- | src/testdir/test_autocmd.vim | 18 | ||||
-rw-r--r-- | src/version.c | 2 |
3 files changed, 54 insertions, 6 deletions
@@ -2950,6 +2950,25 @@ test_for_static(tagptrs_T *tagp) } /* + * 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. * * The line that we get looks like this: @@ -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); diff --git a/src/testdir/test_autocmd.vim b/src/testdir/test_autocmd.vim index 6ca3b220e6..aa7d157799 100644 --- a/src/testdir/test_autocmd.vim +++ b/src/testdir/test_autocmd.vim @@ -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 diff --git a/src/version.c b/src/version.c index a84c8e26ce..1c48ef4c75 100644 --- a/src/version.c +++ b/src/version.c @@ -762,6 +762,8 @@ static char *(features[]) = static int included_patches[] = { /* Add new patch number below this line */ /**/ + 1218, +/**/ 1217, /**/ 1216, |