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