Mercurial > vim
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; |