comparison src/tag.c @ 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 68d7bc045dbe
children 63fdea6e9c6c
comparison
equal deleted inserted replaced
12679:9b185c69b714 12680:429bf1b9292f
2948 2948
2949 return FALSE; 2949 return FALSE;
2950 } 2950 }
2951 2951
2952 /* 2952 /*
2953 * Returns the length of a matching tag line.
2954 */
2955 static size_t
2956 matching_line_len(char_u *lbuf)
2957 {
2958 char_u *p = lbuf + 1;
2959
2960 /* does the same thing as parse_match() */
2961 p += STRLEN(p) + 2;
2962 #ifdef FEAT_EMACS_TAGS
2963 if (*p)
2964 p += STRLEN(p);
2965 else
2966 ++p;
2967 #endif
2968 return (p - lbuf) + STRLEN(p);
2969 }
2970
2971 /*
2953 * Parse a line from a matching tag. Does not change the line itself. 2972 * Parse a line from a matching tag. Does not change the line itself.
2954 * 2973 *
2955 * The line that we get looks like this: 2974 * The line that we get looks like this:
2956 * Emacs tag: <mtt><tag_fname><NUL><ebuf><NUL><lbuf> 2975 * Emacs tag: <mtt><tag_fname><NUL><ebuf><NUL><lbuf>
2957 * other tag: <mtt><tag_fname><NUL><NUL><lbuf> 2976 * other tag: <mtt><tag_fname><NUL><NUL><lbuf>
3069 * 3088 *
3070 * returns OK for success, NOTAGFILE when file not found, FAIL otherwise. 3089 * returns OK for success, NOTAGFILE when file not found, FAIL otherwise.
3071 */ 3090 */
3072 static int 3091 static int
3073 jumpto_tag( 3092 jumpto_tag(
3074 char_u *lbuf, /* line from the tags file for this tag */ 3093 char_u *lbuf_arg, /* line from the tags file for this tag */
3075 int forceit, /* :ta with ! */ 3094 int forceit, /* :ta with ! */
3076 int keep_help) /* keep help flag (FALSE for cscope) */ 3095 int keep_help) /* keep help flag (FALSE for cscope) */
3077 { 3096 {
3078 int save_secure; 3097 int save_secure;
3079 int save_magic; 3098 int save_magic;
3080 int save_p_ws, save_p_scs, save_p_ic; 3099 int save_p_ws, save_p_scs, save_p_ic;
3081 linenr_T save_lnum; 3100 linenr_T save_lnum;
3082 int csave = 0;
3083 char_u *str; 3101 char_u *str;
3084 char_u *pbuf; /* search pattern buffer */ 3102 char_u *pbuf; /* search pattern buffer */
3085 char_u *pbuf_end; 3103 char_u *pbuf_end;
3086 char_u *tofree_fname = NULL; 3104 char_u *tofree_fname = NULL;
3087 char_u *fname; 3105 char_u *fname;
3097 #endif 3115 #endif
3098 char_u *full_fname = NULL; 3116 char_u *full_fname = NULL;
3099 #ifdef FEAT_FOLDING 3117 #ifdef FEAT_FOLDING
3100 int old_KeyTyped = KeyTyped; /* getting the file may reset it */ 3118 int old_KeyTyped = KeyTyped; /* getting the file may reset it */
3101 #endif 3119 #endif
3120 size_t len;
3121 char_u *lbuf;
3122
3123 /* Make a copy of the line, it can become invalid when an autocommand calls
3124 * back here recursively. */
3125 len = matching_line_len(lbuf_arg) + 1;
3126 lbuf = alloc((int)len);
3127 if (lbuf != NULL)
3128 mch_memmove(lbuf, lbuf_arg, len);
3102 3129
3103 pbuf = alloc(LSIZE); 3130 pbuf = alloc(LSIZE);
3104 3131
3105 /* parse the match line into the tagp structure */ 3132 /* parse the match line into the tagp structure */
3106 if (pbuf == NULL || parse_match(lbuf, &tagp) == FAIL) 3133 if (pbuf == NULL || lbuf == NULL || parse_match(lbuf, &tagp) == FAIL)
3107 { 3134 {
3108 tagp.fname_end = NULL; 3135 tagp.fname_end = NULL;
3109 goto erret; 3136 goto erret;
3110 } 3137 }
3111 3138
3112 /* truncate the file name, so it can be used as a string */ 3139 /* truncate the file name, so it can be used as a string */
3113 csave = *tagp.fname_end;
3114 *tagp.fname_end = NUL; 3140 *tagp.fname_end = NUL;
3115 fname = tagp.fname; 3141 fname = tagp.fname;
3116 3142
3117 /* copy the command to pbuf[], remove trailing CR/NL */ 3143 /* copy the command to pbuf[], remove trailing CR/NL */
3118 str = tagp.command; 3144 str = tagp.command;
3244 keep_help_flag = bt_help(curwin_save->w_buffer); 3270 keep_help_flag = bt_help(curwin_save->w_buffer);
3245 else 3271 else
3246 #endif 3272 #endif
3247 keep_help_flag = curbuf->b_help; 3273 keep_help_flag = curbuf->b_help;
3248 } 3274 }
3275
3249 if (getfile_result == GETFILE_UNUSED) 3276 if (getfile_result == GETFILE_UNUSED)
3277 /* Careful: getfile() may trigger autocommands and call jumpto_tag()
3278 * recursively. */
3250 getfile_result = getfile(0, fname, NULL, TRUE, (linenr_T)0, forceit); 3279 getfile_result = getfile(0, fname, NULL, TRUE, (linenr_T)0, forceit);
3251 keep_help_flag = FALSE; 3280 keep_help_flag = FALSE;
3252 3281
3253 if (GETFILE_SUCCESS(getfile_result)) /* got to the right file */ 3282 if (GETFILE_SUCCESS(getfile_result)) /* got to the right file */
3254 { 3283 {
3439 3468
3440 erret: 3469 erret:
3441 #if defined(FEAT_QUICKFIX) 3470 #if defined(FEAT_QUICKFIX)
3442 g_do_tagpreview = 0; /* For next time */ 3471 g_do_tagpreview = 0; /* For next time */
3443 #endif 3472 #endif
3444 if (tagp.fname_end != NULL) 3473 vim_free(lbuf);
3445 *tagp.fname_end = csave;
3446 vim_free(pbuf); 3474 vim_free(pbuf);
3447 vim_free(tofree_fname); 3475 vim_free(tofree_fname);
3448 vim_free(full_fname); 3476 vim_free(full_fname);
3449 3477
3450 return retval; 3478 return retval;