Patch 8.0.1420
Problem: Accessing freed memory in vimgrep.
Solution: Check that the quickfix list is still valid. (Yegappan Lakshmanan,
closes #2474)
Files: src/quickfix.c, src/testdir/test_autocmd.vim,
src/testdir/test_quickfix.vim
*** ../vim-8.0.1419/src/quickfix.c 2017-12-19 16:48:50.926397195 +0100
--- src/quickfix.c 2017-12-21 20:52:46.422018472 +0100
***************
*** 144,149 ****
--- 144,150 ----
static char_u *qf_push_dir(char_u *, struct dir_stack_T **, int
is_file_stack);
static char_u *qf_pop_dir(struct dir_stack_T **);
static char_u *qf_guess_filepath(qf_info_T *qi, int qf_idx, char_u *);
+ static int qflist_valid(win_T *wp, int_u qf_id);
static void qf_fmt_text(char_u *text, char_u *buf, int bufsize);
static void qf_clean_dir_stack(struct dir_stack_T **);
static int qf_win_pos_update(qf_info_T *qi, int old_qf_index);
***************
*** 177,182 ****
--- 178,186 ----
static char_u *qf_last_bufname = NULL;
static bufref_T qf_last_bufref = {NULL, 0, 0};
+ static char *e_loc_list_changed =
+ N_("E926: Current location list was changed");
+
/*
* Read the errorfile "efile" into memory, line by line, building the error
* list. Set the error list's title to qf_title.
***************
*** 1928,1933 ****
--- 1932,1960 ----
}
/*
+ * Returns TRUE if a quickfix/location list with the given identifier exists.
+ */
+ static int
+ qflist_valid (win_T *wp, int_u qf_id)
+ {
+ qf_info_T *qi = &ql_info;
+ int i;
+
+ if (wp != NULL)
+ {
+ qi = GET_LOC_LIST(wp); /* Location list */
+ if (qi == NULL)
+ return FALSE;
+ }
+
+ for (i = 0; i < qi->qf_listcount; ++i)
+ if (qi->qf_lists[i].qf_id == qf_id)
+ return TRUE;
+
+ return FALSE;
+ }
+
+ /*
* When loading a file from the quickfix, the auto commands may modify it.
* This may invalidate the current quickfix entry. This function checks
* whether a entry is still present in the quickfix.
***************
*** 2343,2356 ****
else
{
int old_qf_curlist = qi->qf_curlist;
retval = buflist_getfile(qf_ptr->qf_fnum,
(linenr_T)1, GETF_SETMARK | GETF_SWITCH, forceit);
! if (qi != &ql_info && !win_valid_any_tab(oldwin))
{
! EMSG(_("E924: Current window was closed"));
! *abort = TRUE;
! *opened_window = FALSE;
}
else if (old_qf_curlist != qi->qf_curlist
|| !is_qf_entry_present(qi, qf_ptr))
--- 2370,2397 ----
else
{
int old_qf_curlist = qi->qf_curlist;
+ int save_qfid = qi->qf_lists[qi->qf_curlist].qf_id;
retval = buflist_getfile(qf_ptr->qf_fnum,
(linenr_T)1, GETF_SETMARK | GETF_SWITCH, forceit);
!
! if (qi != &ql_info)
{
! /*
! * Location list. Check whether the associated window is still
! * present and the list is still valid.
! */
! if (!win_valid_any_tab(oldwin))
! {
! EMSG(_("E924: Current window was closed"));
! *abort = TRUE;
! *opened_window = FALSE;
! }
! else if (!qflist_valid(oldwin, save_qfid))
! {
! EMSG(_(e_loc_list_changed));
! *abort = TRUE;
! }
}
else if (old_qf_curlist != qi->qf_curlist
|| !is_qf_entry_present(qi, qf_ptr))
***************
*** 2358,2364 ****
if (qi == &ql_info)
EMSG(_("E925: Current quickfix was changed"));
else
! EMSG(_("E926: Current location list was changed"));
*abort = TRUE;
}
--- 2399,2405 ----
if (qi == &ql_info)
EMSG(_("E925: Current quickfix was changed"));
else
! EMSG(_(e_loc_list_changed));
*abort = TRUE;
}
***************
*** 4065,4070 ****
--- 4106,4112 ----
qf_info_T *qi = &ql_info;
#ifdef FEAT_AUTOCMD
char_u *au_name = NULL;
+ int save_qfid;
#endif
int res;
***************
*** 4122,4129 ****
--- 4164,4178 ----
if (res >= 0 && qi != NULL)
qf_list_changed(qi, qi->qf_curlist);
#ifdef FEAT_AUTOCMD
+ save_qfid = qi->qf_lists[qi->qf_curlist].qf_id;
if (au_name != NULL)
apply_autocmds(EVENT_QUICKFIXCMDPOST, au_name, NULL, FALSE, curbuf);
+ /*
+ * Autocmd might have freed the quickfix/location list. Check whether it
is
+ * still valid
+ */
+ if (!qflist_valid(wp, save_qfid))
+ return;
#endif
if (res > 0 && (eap->cmdidx == CMD_cfile || eap->cmdidx == CMD_lfile))
{
***************
*** 4149,4156 ****
--- 4198,4208 ----
char_u *p;
int fi;
qf_info_T *qi = &ql_info;
+ int loclist_cmd = FALSE;
#ifdef FEAT_AUTOCMD
+ int_u save_qfid;
qfline_T *cur_qf_start;
+ win_T *wp;
#endif
long lnum;
buf_T *buf;
***************
*** 4204,4209 ****
--- 4256,4262 ----
qi = ll_get_or_alloc_list(curwin);
if (qi == NULL)
return;
+ loclist_cmd = TRUE;
}
if (eap->addr_count > 0)
***************
*** 4274,4281 ****
mch_dirname(dirname_start, MAXPATHL);
#ifdef FEAT_AUTOCMD
! /* Remember the value of qf_start, so that we can check for autocommands
! * changing the current quickfix list. */
cur_qf_start = qi->qf_lists[qi->qf_curlist].qf_start;
#endif
--- 4327,4335 ----
mch_dirname(dirname_start, MAXPATHL);
#ifdef FEAT_AUTOCMD
! /* Remember the current values of the quickfix list and qf_start, so that
! * we can check for autocommands changing the current quickfix list. */
! save_qfid = qi->qf_lists[qi->qf_curlist].qf_id;
cur_qf_start = qi->qf_lists[qi->qf_curlist].qf_start;
#endif
***************
*** 4335,4340 ****
--- 4389,4406 ----
using_dummy = FALSE;
#ifdef FEAT_AUTOCMD
+ if (loclist_cmd)
+ {
+ /*
+ * Verify that the location list is still valid. An autocmd might
+ * have freed the location list.
+ */
+ if (!qflist_valid(curwin, save_qfid))
+ {
+ EMSG(_(e_loc_list_changed));
+ goto theend;
+ }
+ }
if (cur_qf_start != qi->qf_lists[qi->qf_curlist].qf_start)
{
int idx;
***************
*** 4491,4496 ****
--- 4557,4569 ----
if (au_name != NULL)
apply_autocmds(EVENT_QUICKFIXCMDPOST, au_name,
curbuf->b_fname, TRUE, curbuf);
+ /*
+ * The QuickFixCmdPost autocmd may free the quickfix list. Check the list
+ * is still valid.
+ */
+ wp = loclist_cmd ? curwin : NULL;
+ if (!qflist_valid(wp, save_qfid))
+ goto theend;
#endif
/* Jump to first match. */
***************
*** 5543,5549 ****
#endif
/* Must come after autocommands. */
! if (eap->cmdidx == CMD_lbuffer || eap->cmdidx == CMD_lgetbuffer
|| eap->cmdidx == CMD_laddbuffer)
{
qi = ll_get_or_alloc_list(curwin);
--- 5616,5623 ----
#endif
/* Must come after autocommands. */
! if (eap->cmdidx == CMD_lbuffer
! || eap->cmdidx == CMD_lgetbuffer
|| eap->cmdidx == CMD_laddbuffer)
{
qi = ll_get_or_alloc_list(curwin);
***************
*** 5614,5627 ****
#endif
int res;
- if (eap->cmdidx == CMD_lexpr || eap->cmdidx == CMD_lgetexpr
- || eap->cmdidx == CMD_laddexpr)
- {
- qi = ll_get_or_alloc_list(curwin);
- if (qi == NULL)
- return;
- }
-
#ifdef FEAT_AUTOCMD
switch (eap->cmdidx)
{
--- 5688,5693 ----
***************
*** 5643,5648 ****
--- 5709,5723 ----
}
#endif
+ if (eap->cmdidx == CMD_lexpr
+ || eap->cmdidx == CMD_lgetexpr
+ || eap->cmdidx == CMD_laddexpr)
+ {
+ qi = ll_get_or_alloc_list(curwin);
+ if (qi == NULL)
+ return;
+ }
+
/* Evaluate the expression. When the result is a string or a list we can
* use it to fill the errorlist. */
tv = eval_expr(eap->arg, NULL);
*** ../vim-8.0.1419/src/testdir/test_autocmd.vim 2017-12-19
16:41:09.309369068 +0100
--- src/testdir/test_autocmd.vim 2017-12-21 20:46:30.972631215 +0100
***************
*** 1178,1187 ****
call assert_fails('lv½ /x', 'E480')
au!
endfunc
-
- func Test_wipe_cbuffer()
- sv x
- au * * bw
- lb
- au!
- endfunc
--- 1178,1180 ----
*** ../vim-8.0.1419/src/testdir/test_quickfix.vim 2017-12-19
16:48:50.926397195 +0100
--- src/testdir/test_quickfix.vim 2017-12-21 20:46:30.972631215 +0100
***************
*** 3038,3040 ****
--- 3038,3080 ----
call assert_fails('lfile', 'E40')
au! QuickFixCmdPre
endfunc
+
+ " The following test used to crash vim
+ func Test_lbuffer_crash()
+ sv Xtest
+ augroup QF_Test
+ au!
+ au * * bw
+ augroup END
+ lbuffer
+ augroup QF_Test
+ au!
+ augroup END
+ endfunc
+
+ " The following test used to crash vim
+ func Test_lexpr_crash()
+ augroup QF_Test
+ au!
+ au * * call setloclist(0, [], 'f')
+ augroup END
+ lexpr ""
+ augroup QF_Test
+ au!
+ augroup END
+ enew | only
+ endfunc
+
+ " The following test used to crash Vim
+ func Test_lvimgrep_crash()
+ sv Xtest
+ augroup QF_Test
+ au!
+ au * * call setloclist(0, [], 'f')
+ augroup END
+ lvimgrep quickfix test_quickfix.vim
+ augroup QF_Test
+ au!
+ augroup END
+ enew | only
+ endfunc
*** ../vim-8.0.1419/src/version.c 2017-12-21 20:27:40.768178638 +0100
--- src/version.c 2017-12-21 20:54:37.085259565 +0100
***************
*** 773,774 ****
--- 773,776 ----
{ /* Add new patch number below this line */
+ /**/
+ 1420,
/**/
--
hundred-and-one symptoms of being an internet addict:
145. You e-mail your boss, informing him you'll be late.
/// Bram Moolenaar -- [email protected] -- http://www.Moolenaar.net \\\
/// sponsor Vim, vote for features -- http://www.Vim.org/sponsor/ \\\
\\\ an exciting new programming language -- http://www.Zimbu.org ///
\\\ help me help AIDS victims -- http://ICCF-Holland.org ///
--
--
You received this message from the "vim_dev" maillist.
Do not top-post! Type your reply below the text you are replying to.
For more information, visit http://www.vim.org/maillist.php
---
You received this message because you are subscribed to the Google Groups
"vim_dev" group.
To unsubscribe from this group and stop receiving emails from it, send an email
to [email protected].
For more options, visit https://groups.google.com/d/optout.