forked from aniani/vim
updated for version 7.4.251
Problem: Crash when BufAdd autocommand wipes out the buffer. Solution: Check for buffer to still be valid. Postpone freeing the buffer structure. (Hirohito Higashi)
This commit is contained in:
18
src/buffer.c
18
src/buffer.c
@@ -676,6 +676,14 @@ free_buffer(buf)
|
|||||||
#endif
|
#endif
|
||||||
#ifdef FEAT_AUTOCMD
|
#ifdef FEAT_AUTOCMD
|
||||||
aubuflocal_remove(buf);
|
aubuflocal_remove(buf);
|
||||||
|
if (autocmd_busy)
|
||||||
|
{
|
||||||
|
/* Do not free the buffer structure while autocommands are executing,
|
||||||
|
* it's still needed. Free it when autocmd_busy is reset. */
|
||||||
|
buf->b_next = au_pending_free_buf;
|
||||||
|
au_pending_free_buf = buf;
|
||||||
|
}
|
||||||
|
else
|
||||||
#endif
|
#endif
|
||||||
vim_free(buf);
|
vim_free(buf);
|
||||||
}
|
}
|
||||||
@@ -1681,7 +1689,11 @@ buflist_new(ffname, sfname, lnum, flags)
|
|||||||
buf->b_p_bl = TRUE;
|
buf->b_p_bl = TRUE;
|
||||||
#ifdef FEAT_AUTOCMD
|
#ifdef FEAT_AUTOCMD
|
||||||
if (!(flags & BLN_DUMMY))
|
if (!(flags & BLN_DUMMY))
|
||||||
|
{
|
||||||
apply_autocmds(EVENT_BUFADD, NULL, NULL, FALSE, buf);
|
apply_autocmds(EVENT_BUFADD, NULL, NULL, FALSE, buf);
|
||||||
|
if (!buf_valid(buf))
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
return buf;
|
return buf;
|
||||||
@@ -1857,8 +1869,14 @@ buflist_new(ffname, sfname, lnum, flags)
|
|||||||
if (!(flags & BLN_DUMMY))
|
if (!(flags & BLN_DUMMY))
|
||||||
{
|
{
|
||||||
apply_autocmds(EVENT_BUFNEW, NULL, NULL, FALSE, buf);
|
apply_autocmds(EVENT_BUFNEW, NULL, NULL, FALSE, buf);
|
||||||
|
if (!buf_valid(buf))
|
||||||
|
return NULL;
|
||||||
if (flags & BLN_LISTED)
|
if (flags & BLN_LISTED)
|
||||||
|
{
|
||||||
apply_autocmds(EVENT_BUFADD, NULL, NULL, FALSE, buf);
|
apply_autocmds(EVENT_BUFADD, NULL, NULL, FALSE, buf);
|
||||||
|
if (!buf_valid(buf))
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
# ifdef FEAT_EVAL
|
# ifdef FEAT_EVAL
|
||||||
if (aborting()) /* autocmds may abort script processing */
|
if (aborting()) /* autocmds may abort script processing */
|
||||||
return NULL;
|
return NULL;
|
||||||
|
@@ -3343,6 +3343,12 @@ do_ecmd(fnum, ffname, sfname, eap, newlnum, flags, oldwin)
|
|||||||
#endif
|
#endif
|
||||||
buf = buflist_new(ffname, sfname, 0L,
|
buf = buflist_new(ffname, sfname, 0L,
|
||||||
BLN_CURBUF | ((flags & ECMD_SET_HELP) ? 0 : BLN_LISTED));
|
BLN_CURBUF | ((flags & ECMD_SET_HELP) ? 0 : BLN_LISTED));
|
||||||
|
#ifdef FEAT_AUTOCMD
|
||||||
|
/* autocommands may change curwin and curbuf */
|
||||||
|
if (oldwin != NULL)
|
||||||
|
oldwin = curwin;
|
||||||
|
old_curbuf = curbuf;
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
if (buf == NULL)
|
if (buf == NULL)
|
||||||
goto theend;
|
goto theend;
|
||||||
|
@@ -9548,13 +9548,19 @@ apply_autocmds_group(event, fname, fname_io, force, group, buf, eap)
|
|||||||
|
|
||||||
/*
|
/*
|
||||||
* When stopping to execute autocommands, restore the search patterns and
|
* When stopping to execute autocommands, restore the search patterns and
|
||||||
* the redo buffer.
|
* the redo buffer. Free buffers in the au_pending_free_buf list.
|
||||||
*/
|
*/
|
||||||
if (!autocmd_busy)
|
if (!autocmd_busy)
|
||||||
{
|
{
|
||||||
restore_search_patterns();
|
restore_search_patterns();
|
||||||
restoreRedobuff();
|
restoreRedobuff();
|
||||||
did_filetype = FALSE;
|
did_filetype = FALSE;
|
||||||
|
while (au_pending_free_buf != NULL)
|
||||||
|
{
|
||||||
|
buf_T *b = au_pending_free_buf->b_next;
|
||||||
|
vim_free(au_pending_free_buf);
|
||||||
|
au_pending_free_buf = b;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
@@ -386,6 +386,11 @@ EXTERN int keep_filetype INIT(= FALSE); /* value for did_filetype when
|
|||||||
/* When deleting the current buffer, another one must be loaded. If we know
|
/* When deleting the current buffer, another one must be loaded. If we know
|
||||||
* which one is preferred, au_new_curbuf is set to it */
|
* which one is preferred, au_new_curbuf is set to it */
|
||||||
EXTERN buf_T *au_new_curbuf INIT(= NULL);
|
EXTERN buf_T *au_new_curbuf INIT(= NULL);
|
||||||
|
|
||||||
|
/* When deleting the buffer and autocmd_busy is TRUE, do not free the buffer
|
||||||
|
* but link it in the list starting with au_pending_free_buf, using b_next.
|
||||||
|
* Free the buffer when autocmd_busy is set to FALSE. */
|
||||||
|
EXTERN buf_T *au_pending_free_buf INIT(= NULL);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifdef FEAT_MOUSE
|
#ifdef FEAT_MOUSE
|
||||||
|
@@ -734,6 +734,8 @@ static char *(features[]) =
|
|||||||
|
|
||||||
static int included_patches[] =
|
static int included_patches[] =
|
||||||
{ /* Add new patch number below this line */
|
{ /* Add new patch number below this line */
|
||||||
|
/**/
|
||||||
|
251,
|
||||||
/**/
|
/**/
|
||||||
250,
|
250,
|
||||||
/**/
|
/**/
|
||||||
|
Reference in New Issue
Block a user