commit d1189ea508c888ebf7468be3872c975e4ea264bb
parent a2b97209395e4ecdec5d7df4f74be067f655a158
Author: Sean Dewar <6256228+seandewar@users.noreply.github.com>
Date: Sun, 21 Dec 2025 20:31:05 +0000
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.
Diffstat:
2 files changed, 18 insertions(+), 2 deletions(-)
diff --git 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
@@ -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)