Hi Bram and Vim developers,

I received a bug report from Hideto Kihara on vim-jp.

Vim 7.4.250 on Fedora19 (64bit)

[Pattern #1]
How to reproduce.
  $ vim -N -u NONE
  :autocmd BufAdd x bwipeout! | call setline(1, repeat([repeat('x', 1000)], 
10000))
  :edit x

Expected behavior
  Display an unnamed buffer that was filled with x.

Actual behavior
  SEGV

Solution
- I adds buffer validation check after apply_autocmds() in buflist_new().
  Like below:
    if (!buf_valid(buf))
        return NULL;

- When deleting the buffer in autocmd_busy is TRUE, Pending vim_free(buf) and
  remember buf.  I do free when autocmd_busy became FALSE.
  Prevent erroneous judgment of 'buf_valid(buf)', When being reused buf
  address in autocommand.
  (It's rare case. But a thing that happens.)


------------
[Pattern #2]
How to reproduce.
  $ vim -N -u NONE
  :autocmd BufAdd z bwipeout! | edit w
  :edit x
  :new y
  :edit z

Expected behavior
  Display an new buffer z.
  And listed buffer is z, x and w. (x is alternate buffer)

Actual behavior
  SEGV

Solution
- I update oldwin and old_curbuf after buflist_new() in do_ecmd().


I attached a patch.
Please check this.

Thanks for reading my crazy English.

Best regards,
Hirohito Higashi

-- 
-- 
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.
diff -r 755931e042e4 src/buffer.c
--- a/src/buffer.c	Sat Apr 05 22:55:53 2014 +0200
+++ b/src/buffer.c	Sun Apr 06 19:11:24 2014 +0900
@@ -676,8 +676,14 @@
 #endif
 #ifdef FEAT_AUTOCMD
     aubuflocal_remove(buf);
-#endif
-    vim_free(buf);
+    if (autocmd_busy)
+    {
+	buf->b_next = au_pending_free_buf;
+	au_pending_free_buf = buf;
+    }
+    else
+#endif
+	vim_free(buf);
 }
 
 /*
@@ -1681,7 +1687,11 @@
 	    buf->b_p_bl = TRUE;
 #ifdef FEAT_AUTOCMD
 	    if (!(flags & BLN_DUMMY))
+	    {
 		apply_autocmds(EVENT_BUFADD, NULL, NULL, FALSE, buf);
+		if (!buf_valid(buf))
+		    return NULL;
+	    }
 #endif
 	}
 	return buf;
@@ -1857,8 +1867,14 @@
     if (!(flags & BLN_DUMMY))
     {
 	apply_autocmds(EVENT_BUFNEW, NULL, NULL, FALSE, buf);
+	if (!buf_valid(buf))
+	    return NULL;
 	if (flags & BLN_LISTED)
+	{
 	    apply_autocmds(EVENT_BUFADD, NULL, NULL, FALSE, buf);
+	    if (!buf_valid(buf))
+		return NULL;
+	}
 # ifdef FEAT_EVAL
 	if (aborting())		/* autocmds may abort script processing */
 	    return NULL;
diff -r 755931e042e4 src/ex_cmds.c
--- a/src/ex_cmds.c	Sat Apr 05 22:55:53 2014 +0200
+++ b/src/ex_cmds.c	Sun Apr 06 19:11:24 2014 +0900
@@ -3343,6 +3343,11 @@
 #endif
 	    buf = buflist_new(ffname, sfname, 0L,
 		    BLN_CURBUF | ((flags & ECMD_SET_HELP) ? 0 : BLN_LISTED));
+#ifdef FEAT_AUTOCMD
+	    /* autocommands may change curwin and curbuf */
+	    oldwin = curwin;
+	    old_curbuf = curbuf;
+#endif
 	}
 	if (buf == NULL)
 	    goto theend;
diff -r 755931e042e4 src/fileio.c
--- a/src/fileio.c	Sat Apr 05 22:55:53 2014 +0200
+++ b/src/fileio.c	Sun Apr 06 19:11:24 2014 +0900
@@ -9552,9 +9552,16 @@
      */
     if (!autocmd_busy)
     {
+	buf_T *b;
+
 	restore_search_patterns();
 	restoreRedobuff();
 	did_filetype = FALSE;
+	for (; au_pending_free_buf != NULL; au_pending_free_buf = b)
+	{
+	    b = au_pending_free_buf->b_next;
+	    vim_free(au_pending_free_buf);
+	}
     }
 
     /*
diff -r 755931e042e4 src/globals.h
--- a/src/globals.h	Sat Apr 05 22:55:53 2014 +0200
+++ b/src/globals.h	Sun Apr 06 19:11:24 2014 +0900
@@ -386,6 +386,11 @@
 /* When deleting the current buffer, another one must be loaded.  If we know
  * which one is preferred, au_new_curbuf is set to it */
 EXTERN buf_T	*au_new_curbuf INIT(= NULL);
+/* When deleting the buffer in autocmd_busy is TRUE, Pending vim_free(buf) and
+ * remember buf.  I do free when autocmd_busy became FALSE.
+ * (Prevent erroneous judgment of 'buf_valid(buf)', When being reused buf
+ * address in autocommand) */
+EXTERN buf_T	*au_pending_free_buf INIT(= NULL);
 #endif
 
 #ifdef FEAT_MOUSE

Raspunde prin e-mail lui