comparison src/quickfix.c @ 22256:c3c9830c7cdc v8.2.1677

patch 8.2.1677: memory access errors when calling setloclist() in autocommand Commit: https://github.com/vim/vim/commit/4d170af0a9379da64d67dc3fa7cc7297956c6f52 Author: Bram Moolenaar <Bram@vim.org> Date: Sun Sep 13 22:21:22 2020 +0200 patch 8.2.1677: memory access errors when calling setloclist() in autocommand Problem: Memory access errors when calling setloclist() in an autocommand. Solution: Give an error if the list was changed unexpectedly. (closes https://github.com/vim/vim/issues/6946)
author Bram Moolenaar <Bram@vim.org>
date Sun, 13 Sep 2020 22:30:03 +0200
parents faaf88167b58
children 849c6f766b19
comparison
equal deleted inserted replaced
22255:8b74d01f1dd6 22256:c3c9830c7cdc
214 * to make this a lot faster if there are multiple matches in the same file. 214 * to make this a lot faster if there are multiple matches in the same file.
215 */ 215 */
216 static char_u *qf_last_bufname = NULL; 216 static char_u *qf_last_bufname = NULL;
217 static bufref_T qf_last_bufref = {NULL, 0, 0}; 217 static bufref_T qf_last_bufref = {NULL, 0, 0};
218 218
219 static char *e_loc_list_changed = 219 static char *e_current_quickfix_list_was_changed =
220 N_("E925: Current quickfix list was changed");
221 static char *e_current_location_list_was_changed =
220 N_("E926: Current location list was changed"); 222 N_("E926: Current location list was changed");
221 223
222 /* 224 /*
223 * Maximum number of bytes allowed per line while reading a errorfile. 225 * Maximum number of bytes allowed per line while reading a errorfile.
224 */ 226 */
3106 int forceit, 3108 int forceit,
3107 int prev_winid, 3109 int prev_winid,
3108 int *opened_window) 3110 int *opened_window)
3109 { 3111 {
3110 qf_list_T *qfl = qf_get_curlist(qi); 3112 qf_list_T *qfl = qf_get_curlist(qi);
3113 int old_changedtick = qfl->qf_changedtick;
3111 qfltype_T qfl_type = qfl->qfl_type; 3114 qfltype_T qfl_type = qfl->qfl_type;
3112 int retval = OK; 3115 int retval = OK;
3113 int old_qf_curlist = qi->qf_curlist; 3116 int old_qf_curlist = qi->qf_curlist;
3114 int save_qfid = qfl->qf_id; 3117 int save_qfid = qfl->qf_id;
3115 3118
3144 } 3147 }
3145 } 3148 }
3146 3149
3147 if (qfl_type == QFLT_QUICKFIX && !qflist_valid(NULL, save_qfid)) 3150 if (qfl_type == QFLT_QUICKFIX && !qflist_valid(NULL, save_qfid))
3148 { 3151 {
3149 emsg(_("E925: Current quickfix was changed")); 3152 emsg(_(e_current_quickfix_list_was_changed));
3150 return NOTDONE; 3153 return NOTDONE;
3151 } 3154 }
3152 3155
3156 // Check if the list was changed. The pointers may happen to be identical,
3157 // thus also check qf_changedtick.
3153 if (old_qf_curlist != qi->qf_curlist 3158 if (old_qf_curlist != qi->qf_curlist
3159 || old_changedtick != qfl->qf_changedtick
3154 || !is_qf_entry_present(qfl, qf_ptr)) 3160 || !is_qf_entry_present(qfl, qf_ptr))
3155 { 3161 {
3156 if (qfl_type == QFLT_QUICKFIX) 3162 if (qfl_type == QFLT_QUICKFIX)
3157 emsg(_("E925: Current quickfix was changed")); 3163 emsg(_(e_current_quickfix_list_was_changed));
3158 else 3164 else
3159 emsg(_(e_loc_list_changed)); 3165 emsg(_(e_current_location_list_was_changed));
3160 return NOTDONE; 3166 return NOTDONE;
3161 } 3167 }
3162 3168
3163 return retval; 3169 return retval;
3164 } 3170 }
3262 qf_info_T *qi, 3268 qf_info_T *qi,
3263 qfline_T *qf_ptr, 3269 qfline_T *qf_ptr,
3264 int newwin, 3270 int newwin,
3265 int *opened_window) 3271 int *opened_window)
3266 { 3272 {
3273 qf_list_T *qfl = qf_get_curlist(qi);
3274 int old_changedtick = qfl->qf_changedtick;
3275 int old_qf_curlist = qi->qf_curlist;
3276 qfltype_T qfl_type = qfl->qfl_type;
3277
3267 // For ":helpgrep" find a help window or open one. 3278 // For ":helpgrep" find a help window or open one.
3268 if (qf_ptr->qf_type == 1 && (!bt_help(curwin->w_buffer) || cmdmod.tab != 0)) 3279 if (qf_ptr->qf_type == 1 && (!bt_help(curwin->w_buffer) || cmdmod.tab != 0))
3269 if (jump_to_help_window(qi, newwin, opened_window) == FAIL) 3280 if (jump_to_help_window(qi, newwin, opened_window) == FAIL)
3270 return FAIL; 3281 return FAIL;
3282 if (old_qf_curlist != qi->qf_curlist
3283 || old_changedtick != qfl->qf_changedtick
3284 || !is_qf_entry_present(qfl, qf_ptr))
3285 {
3286 if (qfl_type == QFLT_QUICKFIX)
3287 emsg(_(e_current_quickfix_list_was_changed));
3288 else
3289 emsg(_(e_current_location_list_was_changed));
3290 return FAIL;
3291 }
3271 3292
3272 // If currently in the quickfix window, find another window to show the 3293 // If currently in the quickfix window, find another window to show the
3273 // file in. 3294 // file in.
3274 if (bt_quickfix(curbuf) && !*opened_window) 3295 if (bt_quickfix(curbuf) && !*opened_window)
3275 { 3296 {
3279 return NOTDONE; 3300 return NOTDONE;
3280 3301
3281 if (qf_jump_to_usable_window(qf_ptr->qf_fnum, newwin, 3302 if (qf_jump_to_usable_window(qf_ptr->qf_fnum, newwin,
3282 opened_window) == FAIL) 3303 opened_window) == FAIL)
3283 return FAIL; 3304 return FAIL;
3305 }
3306 if (old_qf_curlist != qi->qf_curlist
3307 || old_changedtick != qfl->qf_changedtick
3308 || !is_qf_entry_present(qfl, qf_ptr))
3309 {
3310 if (qfl_type == QFLT_QUICKFIX)
3311 emsg(_(e_current_quickfix_list_was_changed));
3312 else
3313 emsg(_(e_current_location_list_was_changed));
3314 return FAIL;
3284 } 3315 }
3285 3316
3286 return OK; 3317 return OK;
3287 } 3318 }
3288 3319
5832 if (!qflist_valid(wp, qfid)) 5863 if (!qflist_valid(wp, qfid))
5833 { 5864 {
5834 if (wp != NULL) 5865 if (wp != NULL)
5835 { 5866 {
5836 // An autocmd has freed the location list. 5867 // An autocmd has freed the location list.
5837 emsg(_(e_loc_list_changed)); 5868 emsg(_(e_current_location_list_was_changed));
5838 return FALSE; 5869 return FALSE;
5839 } 5870 }
5840 else 5871 else
5841 { 5872 {
5842 // Quickfix list is not found, create a new one. 5873 // Quickfix list is not found, create a new one.