Hi Bram!

On So, 28 Okt 2012, Bram Moolenaar wrote:

> 
> Marcin Szamotulski wrote:
> 
> > Here is a way to crash vim (vim -u NONE --noplugin).
> > 
> > Set an autocommand:
> > 
> > au BufUnload * :call setloclist(0, [{'bufnr':1, 'lnum':1, 'col':1, 'text': 
> > 'tango down'}])
> > 
> > Now run:
> > 
> > :lvimgrep /.*/ *.txt
> > 
> > And vim goes down.
> 
> I can reproduce it.
> 
> > Should lvimgrep trigger BufUnload autocommands? Where it is useful?
> 
> Vimgrep works by loading the file into a buffer.  That triggers
> autocommands to be able to search in compressed files and handles
> encoding conversions.  BufUnload may be needed to undo the effect of
> BufRead autocommands.
> 
> I'll put this on the todo list, but it's unlikely that I will be able to
> fix it soon.  I hope someone can make a patch.

Here is a patch including a test.

regards,
Christian

-- 
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
diff --git a/src/quickfix.c b/src/quickfix.c
--- a/src/quickfix.c
+++ b/src/quickfix.c
@@ -107,7 +107,7 @@
 };
 
 static int	qf_init_ext __ARGS((qf_info_T *qi, char_u *efile, buf_T *buf, typval_T *tv, char_u *errorformat, int newlist, linenr_T lnumfirst, linenr_T lnumlast, char_u *qf_title));
-static void	qf_new_list __ARGS((qf_info_T *qi, char_u *qf_title));
+static void	qf_new_list __ARGS((qf_info_T *qi, char_u *qf_title, win_T *wp));
 static void	ll_free_all __ARGS((qf_info_T **pqi));
 static int	qf_add_entry __ARGS((qf_info_T *qi, qfline_T **prevp, char_u *dir, char_u *fname, int bufnum, char_u *mesg, long lnum, int col, int vis_col, char_u *pattern, int nr, int type, int valid));
 static qf_info_T *ll_new_list __ARGS((void));
@@ -266,7 +266,7 @@
 
     if (newlist || qi->qf_curlist == qi->qf_listcount)
 	/* make place for a new list */
-	qf_new_list(qi, qf_title);
+	qf_new_list(qi, qf_title, curwin);
     else if (qi->qf_lists[qi->qf_curlist].qf_count > 0)
 	/* Adding to existing list, find last entry. */
 	for (qfprev = qi->qf_lists[qi->qf_curlist].qf_start;
@@ -885,9 +885,10 @@
  * Prepare for adding a new quickfix list.
  */
     static void
-qf_new_list(qi, qf_title)
+qf_new_list(qi, qf_title, wp)
     qf_info_T	*qi;
     char_u	*qf_title;
+    win_T	*wp;
 {
     int		i;
 
@@ -897,7 +898,11 @@
      * way with ":grep'.
      */
     while (qi->qf_listcount > qi->qf_curlist + 1)
+    {
+	if (wp->w_llist == qi)
+	    wp->w_llist = NULL;
 	qf_free(qi, --qi->qf_listcount);
+    }
 
     /*
      * When the stack is full, remove to oldest entry
@@ -905,6 +910,8 @@
      */
     if (qi->qf_listcount == LISTCOUNT)
     {
+	if (wp->w_llist == qi)
+	    wp->w_llist = NULL;
 	qf_free(qi, 0);
 	for (i = 1; i < LISTCOUNT; ++i)
 	    qi->qf_lists[i - 1] = qi->qf_lists[i];
@@ -996,6 +1003,8 @@
 	qfp->qf_fnum = bufnum;
     else
 	qfp->qf_fnum = qf_get_fnum(dir, fname);
+/*    if (*mesg == NUL)
+	qfp->qf_text = NULL; */
     if ((qfp->qf_text = vim_strsave(mesg)) == NULL)
     {
 	vim_free(qfp);
@@ -3181,7 +3190,7 @@
 	 eap->cmdidx != CMD_vimgrepadd && eap->cmdidx != CMD_lvimgrepadd)
 					|| qi->qf_curlist == qi->qf_listcount)
 	/* make place for a new list */
-	qf_new_list(qi, *eap->cmdlinep);
+	qf_new_list(qi, *eap->cmdlinep, curwin);
     else if (qi->qf_lists[qi->qf_curlist].qf_count > 0)
 	/* Adding to existing list, find last entry. */
 	for (prevp = qi->qf_lists[qi->qf_curlist].qf_start;
@@ -3747,7 +3756,7 @@
 
     if (action == ' ' || qi->qf_curlist == qi->qf_listcount)
 	/* make place for a new list */
-	qf_new_list(qi, title);
+	qf_new_list(qi, title, wp);
     else if (action == 'a' && qi->qf_lists[qi->qf_curlist].qf_count > 0)
 	/* Adding to existing list, find last entry. */
 	for (prevp = qi->qf_lists[qi->qf_curlist].qf_start;
@@ -4029,7 +4038,7 @@
 #endif
 
 	/* create a new quickfix list */
-	qf_new_list(qi, *eap->cmdlinep);
+	qf_new_list(qi, *eap->cmdlinep, wp);
 
 	/* Go through all directories in 'runtimepath' */
 	p = p_rtp;
diff --git a/src/testdir/test49.ok b/src/testdir/test49.ok
--- a/src/testdir/test49.ok
+++ b/src/testdir/test49.ok
@@ -85,8 +85,10 @@
 *** Test  83: OK (2835)
 *** Test  84: OK (934782101)
 *** Test  85: OK (198689)
---- Test  86: All tests were run with throwing exceptions on error.
+--- Test  86: No Crash for vimgrep on BufUnload
+*** Test  86: OK (0)
+--- Test  87: All tests were run with throwing exceptions on error.
 	      The $VIMNOERRTHROW control is not configured.
---- Test  86: All tests were run with throwing exceptions on interrupt.
+--- Test  87: All tests were run with throwing exceptions on interrupt.
 	      The $VIMNOINTTHROW control is not configured.
-*** Test  86: OK (50443995)
+*** Test  87: OK (50443995)
diff --git a/src/testdir/test49.vim b/src/testdir/test49.vim
--- a/src/testdir/test49.vim
+++ b/src/testdir/test49.vim
@@ -9603,9 +9603,28 @@
 
 Xcheck 198689
 
-
-"-------------------------------------------------------------------------------
-" Test 86:  $VIMNOERRTHROW and $VIMNOINTTHROW support			    {{{1
+"-------------------------------------------------------------------------------
+" Test 86   setloclist crash						    {{{1
+"
+"	    Executing a setloclist() on BufUnload shouldn't crash Vim
+"-------------------------------------------------------------------------------
+
+func F
+    au BufUnload * :call setloclist(0, [{'bufnr':1, 'lnum':1, 'col':1, 'text': 'tango down'}])
+
+    :lvimgrep /.*/ *
+endfunc
+
+XpathINIT
+
+ExecAsScript F
+
+delfunction F
+Xout  "No Crash for vimgrep on BufUnload"
+Xcheck 0 
+
+"-------------------------------------------------------------------------------
+" Test 87:  $VIMNOERRTHROW and $VIMNOINTTHROW support			    {{{1
 "
 "	    It is possible to configure Vim for throwing exceptions on error
 "	    or interrupt, controlled by variables $VIMNOERRTHROW and

Raspunde prin e-mail lui