forked from aniani/vim
Problem: crash with WinNewPre autocommand
Problem: crash with WinNewPre autocommand, because window structures are not yet safe to use Solution: Don't trigger WinNewPre on :tabnew Signed-off-by: Christian Brabandt <cb@256bit.org>
This commit is contained in:
@@ -1,4 +1,4 @@
|
|||||||
*autocmd.txt* For Vim version 9.1. Last change: 2024 Jul 17
|
*autocmd.txt* For Vim version 9.1. Last change: 2024 Aug 10
|
||||||
|
|
||||||
|
|
||||||
VIM REFERENCE MANUAL by Bram Moolenaar
|
VIM REFERENCE MANUAL by Bram Moolenaar
|
||||||
@@ -1427,8 +1427,10 @@ WinLeave Before leaving a window. If the window to be
|
|||||||
*WinNewPre*
|
*WinNewPre*
|
||||||
WinNewPre Before creating a new window. Triggered
|
WinNewPre Before creating a new window. Triggered
|
||||||
before commands that modify window layout by
|
before commands that modify window layout by
|
||||||
creating a split or new tab page. Not done for
|
creating a split.
|
||||||
the first window, when Vim has just started.
|
Not done for creating tabs or for the first
|
||||||
|
window, as the window structure is not
|
||||||
|
initialized yet and so is generally not safe.
|
||||||
It is not allowed to modify window layout
|
It is not allowed to modify window layout
|
||||||
while executing commands for the WinNewPre
|
while executing commands for the WinNewPre
|
||||||
event.
|
event.
|
||||||
|
BIN
src/testdir/crash/nullpointer
Normal file
BIN
src/testdir/crash/nullpointer
Normal file
Binary file not shown.
@@ -14,6 +14,13 @@ func s:cleanup_buffers() abort
|
|||||||
endfor
|
endfor
|
||||||
endfunc
|
endfunc
|
||||||
|
|
||||||
|
func CleanUpTestAuGroup()
|
||||||
|
augroup testing
|
||||||
|
au!
|
||||||
|
augroup END
|
||||||
|
augroup! testing
|
||||||
|
endfunc
|
||||||
|
|
||||||
func Test_vim_did_enter()
|
func Test_vim_did_enter()
|
||||||
call assert_false(v:vim_did_enter)
|
call assert_false(v:vim_did_enter)
|
||||||
|
|
||||||
@@ -269,6 +276,7 @@ endfunc
|
|||||||
func Test_win_tab_autocmd()
|
func Test_win_tab_autocmd()
|
||||||
let g:record = []
|
let g:record = []
|
||||||
|
|
||||||
|
defer CleanUpTestAuGroup()
|
||||||
augroup testing
|
augroup testing
|
||||||
au WinNewPre * call add(g:record, 'WinNewPre')
|
au WinNewPre * call add(g:record, 'WinNewPre')
|
||||||
au WinNew * call add(g:record, 'WinNew')
|
au WinNew * call add(g:record, 'WinNew')
|
||||||
@@ -288,7 +296,7 @@ func Test_win_tab_autocmd()
|
|||||||
|
|
||||||
call assert_equal([
|
call assert_equal([
|
||||||
\ 'WinNewPre', 'WinLeave', 'WinNew', 'WinEnter',
|
\ 'WinNewPre', 'WinLeave', 'WinNew', 'WinEnter',
|
||||||
\ 'WinLeave', 'TabLeave', 'WinNewPre', 'WinNew', 'WinEnter', 'TabNew', 'TabEnter',
|
\ 'WinLeave', 'TabLeave', 'WinNew', 'WinEnter', 'TabNew', 'TabEnter',
|
||||||
\ 'WinLeave', 'TabLeave', 'WinClosed', 'TabClosed', 'WinEnter', 'TabEnter',
|
\ 'WinLeave', 'TabLeave', 'WinClosed', 'TabClosed', 'WinEnter', 'TabEnter',
|
||||||
\ 'WinLeave', 'WinClosed', 'WinEnter'
|
\ 'WinLeave', 'WinClosed', 'WinEnter'
|
||||||
\ ], g:record)
|
\ ], g:record)
|
||||||
@@ -299,7 +307,7 @@ func Test_win_tab_autocmd()
|
|||||||
bwipe somefile
|
bwipe somefile
|
||||||
|
|
||||||
call assert_equal([
|
call assert_equal([
|
||||||
\ 'WinLeave', 'TabLeave', 'WinNewPre', 'WinNew', 'WinEnter', 'TabNew', 'TabEnter',
|
\ 'WinLeave', 'TabLeave', 'WinNew', 'WinEnter', 'TabNew', 'TabEnter',
|
||||||
\ 'WinLeave', 'TabLeave', 'WinEnter', 'TabEnter',
|
\ 'WinLeave', 'TabLeave', 'WinEnter', 'TabEnter',
|
||||||
\ 'WinClosed', 'TabClosed'
|
\ 'WinClosed', 'TabClosed'
|
||||||
\ ], g:record)
|
\ ], g:record)
|
||||||
@@ -316,9 +324,6 @@ func Test_win_tab_autocmd()
|
|||||||
\ 'WinNewPre', 'WinLeave', 'WinNew', 'WinEnter'
|
\ 'WinNewPre', 'WinLeave', 'WinNew', 'WinEnter'
|
||||||
\ ], g:record)
|
\ ], g:record)
|
||||||
|
|
||||||
augroup testing
|
|
||||||
au!
|
|
||||||
augroup END
|
|
||||||
unlet g:record
|
unlet g:record
|
||||||
endfunc
|
endfunc
|
||||||
|
|
||||||
@@ -330,17 +335,15 @@ func Test_WinNewPre()
|
|||||||
au WinNewPre * call add(g:layouts_pre, winlayout())
|
au WinNewPre * call add(g:layouts_pre, winlayout())
|
||||||
au WinNew * call add(g:layouts_post, winlayout())
|
au WinNew * call add(g:layouts_post, winlayout())
|
||||||
augroup END
|
augroup END
|
||||||
|
defer CleanUpTestAuGroup()
|
||||||
split
|
split
|
||||||
call assert_notequal(g:layouts_pre[0], g:layouts_post[0])
|
call assert_notequal(g:layouts_pre[0], g:layouts_post[0])
|
||||||
split
|
split
|
||||||
call assert_equal(g:layouts_pre[1], g:layouts_post[0])
|
call assert_equal(g:layouts_pre[1], g:layouts_post[0])
|
||||||
call assert_notequal(g:layouts_pre[1], g:layouts_post[1])
|
call assert_notequal(g:layouts_pre[1], g:layouts_post[1])
|
||||||
|
" not triggered for tabnew
|
||||||
tabnew
|
tabnew
|
||||||
call assert_notequal(g:layouts_pre[2], g:layouts_post[1])
|
call assert_equal(2, len(g:layouts_pre))
|
||||||
call assert_notequal(g:layouts_pre[2], g:layouts_post[2])
|
|
||||||
augroup testing
|
|
||||||
au!
|
|
||||||
augroup END
|
|
||||||
unlet g:layouts_pre
|
unlet g:layouts_pre
|
||||||
unlet g:layouts_post
|
unlet g:layouts_post
|
||||||
|
|
||||||
@@ -383,9 +386,6 @@ func Test_WinNewPre()
|
|||||||
let g:caught += 1
|
let g:caught += 1
|
||||||
endtry
|
endtry
|
||||||
call assert_equal(4, g:caught)
|
call assert_equal(4, g:caught)
|
||||||
augroup testing
|
|
||||||
au!
|
|
||||||
augroup END
|
|
||||||
unlet g:caught
|
unlet g:caught
|
||||||
endfunc
|
endfunc
|
||||||
|
|
||||||
@@ -2807,7 +2807,8 @@ endfunc
|
|||||||
|
|
||||||
func Test_autocmd_nested()
|
func Test_autocmd_nested()
|
||||||
let g:did_nested = 0
|
let g:did_nested = 0
|
||||||
augroup Testing
|
defer CleanUpTestAuGroup()
|
||||||
|
augroup testing
|
||||||
au WinNew * edit somefile
|
au WinNew * edit somefile
|
||||||
au BufNew * let g:did_nested = 1
|
au BufNew * let g:did_nested = 1
|
||||||
augroup END
|
augroup END
|
||||||
@@ -2817,7 +2818,7 @@ func Test_autocmd_nested()
|
|||||||
bwipe! somefile
|
bwipe! somefile
|
||||||
|
|
||||||
" old nested argument still works
|
" old nested argument still works
|
||||||
augroup Testing
|
augroup testing
|
||||||
au!
|
au!
|
||||||
au WinNew * nested edit somefile
|
au WinNew * nested edit somefile
|
||||||
au BufNew * let g:did_nested = 1
|
au BufNew * let g:did_nested = 1
|
||||||
@@ -4831,4 +4832,36 @@ func Test_KeyInputPre()
|
|||||||
au! KeyInputPre
|
au! KeyInputPre
|
||||||
endfunc
|
endfunc
|
||||||
|
|
||||||
|
" those commands caused null pointer access, see #15464
|
||||||
|
func Test_WinNewPre_crash()
|
||||||
|
defer CleanUpTestAuGroup()
|
||||||
|
let _cmdheight=&cmdheight
|
||||||
|
augroup testing
|
||||||
|
au!
|
||||||
|
autocmd WinNewPre * redraw
|
||||||
|
augroup END
|
||||||
|
tabnew
|
||||||
|
tabclose
|
||||||
|
augroup testing
|
||||||
|
au!
|
||||||
|
autocmd WinNewPre * wincmd t
|
||||||
|
augroup END
|
||||||
|
tabnew
|
||||||
|
tabclose
|
||||||
|
augroup testing
|
||||||
|
au!
|
||||||
|
autocmd WinNewPre * wincmd b
|
||||||
|
augroup END
|
||||||
|
tabnew
|
||||||
|
tabclose
|
||||||
|
augroup testing
|
||||||
|
au!
|
||||||
|
autocmd WinNewPre * set cmdheight+=1
|
||||||
|
augroup END
|
||||||
|
tabnew
|
||||||
|
tabclose
|
||||||
|
let &cmdheight=_cmdheight
|
||||||
|
endfunc
|
||||||
|
|
||||||
|
|
||||||
" vim: shiftwidth=2 sts=2 expandtab
|
" vim: shiftwidth=2 sts=2 expandtab
|
||||||
|
@@ -202,6 +202,12 @@ func Test_crash1_3()
|
|||||||
call term_sendkeys(buf, args)
|
call term_sendkeys(buf, args)
|
||||||
call TermWait(buf, 150)
|
call TermWait(buf, 150)
|
||||||
|
|
||||||
|
let file = 'crash/nullpointer'
|
||||||
|
let cmn_args = "%s -u NONE -i NONE -n -e -s -S %s -c ':qa!'\<cr>"
|
||||||
|
let args = printf(cmn_args, vim, file)
|
||||||
|
call term_sendkeys(buf, args)
|
||||||
|
call TermWait(buf, 50)
|
||||||
|
|
||||||
" clean up
|
" clean up
|
||||||
exe buf .. "bw!"
|
exe buf .. "bw!"
|
||||||
bw!
|
bw!
|
||||||
|
@@ -704,6 +704,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 */
|
||||||
|
/**/
|
||||||
|
671,
|
||||||
/**/
|
/**/
|
||||||
670,
|
670,
|
||||||
/**/
|
/**/
|
||||||
|
@@ -4607,6 +4607,11 @@ free_tabpage(tabpage_T *tp)
|
|||||||
* It will edit the current buffer, like after ":split".
|
* It will edit the current buffer, like after ":split".
|
||||||
* When "after" is 0 put it just after the current Tab page.
|
* When "after" is 0 put it just after the current Tab page.
|
||||||
* Otherwise put it just before tab page "after".
|
* Otherwise put it just before tab page "after".
|
||||||
|
*
|
||||||
|
* Does not trigger WinNewPre, since the window structures
|
||||||
|
* are not completly setup yet and could cause dereferencing
|
||||||
|
* NULL pointers
|
||||||
|
*
|
||||||
* Return FAIL or OK.
|
* Return FAIL or OK.
|
||||||
*/
|
*/
|
||||||
int
|
int
|
||||||
@@ -4640,8 +4645,6 @@ win_new_tabpage(int after)
|
|||||||
newtp->tp_localdir = (tp->tp_localdir == NULL)
|
newtp->tp_localdir = (tp->tp_localdir == NULL)
|
||||||
? NULL : vim_strsave(tp->tp_localdir);
|
? NULL : vim_strsave(tp->tp_localdir);
|
||||||
|
|
||||||
trigger_winnewpre();
|
|
||||||
|
|
||||||
// Create a new empty window.
|
// Create a new empty window.
|
||||||
if (win_alloc_firstwin(tp->tp_curwin) == OK)
|
if (win_alloc_firstwin(tp->tp_curwin) == OK)
|
||||||
{
|
{
|
||||||
|
Reference in New Issue
Block a user