Mercurial > vim
changeset 12680:429bf1b9292f v8.0.1218
patch 8.0.1218: writing to freed memory in autocmd
commit https://github.com/vim/vim/commit/8d84ff1a3c8cfe59399d3f675ec080066582fdb6
Author: Bram Moolenaar <Bram@vim.org>
Date: Thu Oct 26 16:42:16 2017 +0200
patch 8.0.1218: writing to freed memory in autocmd
Problem: Writing to freed memory in autocmd.
Solution: Make a copy of the tag line. (Dominique Pelle, closes https://github.com/vim/vim/issues/2245)
author | Christian Brabandt <cb@256bit.org> |
---|---|
date | Thu, 26 Oct 2017 16:45:05 +0200 |
parents | 9b185c69b714 |
children | ebdb4ea1386e |
files | src/tag.c src/testdir/test_autocmd.vim src/version.c |
diffstat | 3 files changed, 54 insertions(+), 6 deletions(-) [+] |
line wrap: on
line diff
--- a/src/tag.c +++ b/src/tag.c @@ -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);
--- 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