From d1189ea508c888ebf7468be3872c975e4ea264bb Mon Sep 17 00:00:00 2001 From: Sean Dewar <6256228+seandewar@users.noreply.github.com> Date: Sun, 21 Dec 2025 20:31:05 +0000 Subject: [PATCH] fix(window): win_move_after UAF from naughty autocmds (#37065) Problem: use-after-free in win_move_after if win_enter autocommands free win1/2. Solution: set w_pos_changed before calling win_enter. --- src/nvim/window.c | 4 ++-- test/functional/autocmd/autocmd_spec.lua | 16 ++++++++++++++++ 2 files changed, 18 insertions(+), 2 deletions(-) diff --git a/src/nvim/window.c b/src/nvim/window.c index d8800c15f9..68f202ce34 100644 --- a/src/nvim/window.c +++ b/src/nvim/window.c @@ -2092,10 +2092,10 @@ void win_move_after(win_T *win1, win_T *win2) win_comp_pos(); // recompute w_winrow for all windows redraw_later(curwin, UPD_NOT_VALID); } - win_enter(win1, false); - win1->w_pos_changed = true; win2->w_pos_changed = true; + + win_enter(win1, false); } /// Compute maximum number of windows that can fit within "height" in frame "fr". diff --git a/test/functional/autocmd/autocmd_spec.lua b/test/functional/autocmd/autocmd_spec.lua index 6618140e23..d48cf0a27c 100644 --- a/test/functional/autocmd/autocmd_spec.lua +++ b/test/functional/autocmd/autocmd_spec.lua @@ -715,4 +715,20 @@ describe('autocmd', function() vim.cmd "tabnew" ]] end) + + it('no use-after-free from win_enter autocommands in win_move_after', function() + exec [[ + split foo + split bar + lcd .. + wincmd b + ]] + eq(fn.winnr('$'), fn.winnr()) + -- Using DirChanged as Enter/Leave autocmds are blocked by :ball here. + exec [[ + autocmd DirChanged * ++once split flarb | only! + ball + ]] + eq('flarb', fn.bufname()) + end) end)