neovim

Neovim text editor
git clone https://git.dasho.dev/neovim.git
Log | Files | Refs | README

commit 4fadc21e3854b9c49c670044b0f84ad8a2f63903
parent 0bef1c88f3621e185b3e35f361a418b8b36ee010
Author: Sean Dewar <6256228+seandewar@users.noreply.github.com>
Date:   Tue, 22 Jul 2025 01:28:45 +0100

fix(window): disallow closing autocmd window in other tabpage

Problem: unlike win_close, win_close_othertab could be used to close the
autocommand window from a different tabpage. This causes aucmd_restbuf to close
the wrong window, potentially causing a crash.

Solution: disallow closing it. Also replace a deprecated use of exc_exec in the
test file.

Fixes #21409.

Diffstat:
Msrc/nvim/window.c | 4++++
Mtest/functional/autocmd/autocmd_spec.lua | 24++++++++++++++++++++++--
2 files changed, 26 insertions(+), 2 deletions(-)

diff --git a/src/nvim/window.c b/src/nvim/window.c @@ -2992,6 +2992,10 @@ bool win_close_othertab(win_T *win, int free_buf, tabpage_T *tp, bool force) || (win->w_buffer != NULL && win->w_buffer->b_locked > 0)) { return false; // window is already being closed } + if (is_aucmd_win(win)) { + emsg(_(e_autocmd_close)); + return false; + } // Check if closing this window would leave only floating windows. if (tp->tp_firstwin == win && win->w_next && win->w_next->w_floating) { diff --git a/test/functional/autocmd/autocmd_spec.lua b/test/functional/autocmd/autocmd_spec.lua @@ -8,6 +8,7 @@ local dedent = t.dedent local eq = t.eq local neq = t.neq local eval = n.eval +local exec = n.exec local feed = n.feed local clear = n.clear local matches = t.matches @@ -16,7 +17,6 @@ local pcall_err = t.pcall_err local fn = n.fn local expect = n.expect local command = n.command -local exc_exec = n.exc_exec local exec_lua = n.exec_lua local retry = t.retry local source = n.source @@ -150,7 +150,10 @@ describe('autocmd', function() }) command('autocmd BufLeave * bwipeout yy') - eq('Vim(edit):E143: Autocommands unexpectedly deleted new buffer yy', exc_exec('edit yy')) + eq( + 'Vim(edit):E143: Autocommands unexpectedly deleted new buffer yy', + pcall_err(command, 'edit yy') + ) expect([[ start of test file xx @@ -428,6 +431,23 @@ describe('autocmd', function() ) end) + it('cannot close `aucmd_win` in non-current tabpage', function() + exec([[ + file Xa + tabnew Xb + call setline(1, 'foo') + tabfirst + autocmd BufWriteCmd Xb tablast | bwipe! Xa + ]]) + eq( + 'BufWriteCmd Autocommands for "Xb": Vim(bwipeout):E813: Cannot close autocmd window', + pcall_err(command, 'wall') + ) + -- Sanity check: :bwipe failing to close all windows into Xa should keep it loaded. + -- (So there's no risk of it being left unloaded inside a window) + eq(1, eval('bufloaded("Xa")')) + end) + describe('closing last non-floating window in tab from `aucmd_win`', function() before_each(function() command('edit Xa.txt')