From 6f370f34f2c24aed0d2acebab23c4bcc86a06d69 Mon Sep 17 00:00:00 2001 From: phanium <91544758+phanen@users.noreply.github.com> Date: Wed, 15 Jul 2026 19:48:34 +0800 Subject: [PATCH] fix(window): remove float grid from compositor layers before free #40731 Problem: Closing a floating window from a non-current tab frees its grid without removing it from the compositor's `layers` table, so the next `ui_comp_put_grid()` walks a dangling pointer (UAF). Solution: Call `ui_comp_remove_grid()` (and `ui_call_win_close()` for multigrid UIs) before `win_free_mem()`, matching `win_close()` since PR #21551. --- src/nvim/window.c | 7 +++++++ test/functional/ui/float_spec.lua | 11 +++++++++++ 2 files changed, 18 insertions(+) diff --git a/src/nvim/window.c b/src/nvim/window.c index 075c1c0493..1db79abd40 100644 --- a/src/nvim/window.c +++ b/src/nvim/window.c @@ -3215,6 +3215,13 @@ bool win_close_othertab(win_T *win, int free_buf, tabpage_T *tp, bool force) } } + if (ui_has(kUIMultigrid)) { + ui_call_win_close(win->w_grid_alloc.handle); + } + if (win->w_floating) { + ui_comp_remove_grid(&win->w_grid_alloc); + } + bufref_T bufref; set_bufref(&bufref, win->w_buffer); diff --git a/test/functional/ui/float_spec.lua b/test/functional/ui/float_spec.lua index 83afe503a5..436ad5bee0 100644 --- a/test/functional/ui/float_spec.lua +++ b/test/functional/ui/float_spec.lua @@ -10523,6 +10523,17 @@ describe('float window', function() end) end) + it('no crash when closing a floating window from a non-current tab', function() + local buf = api.nvim_create_buf(false, true) + local win = api.nvim_open_win(buf, false, { relative = 'editor', width = 5, height = 5, row = 0, col = 0 }) + exec_lua(function() + vim.cmd.tabnew() + vim.api.nvim_win_call(win, vim.cmd.redraw) + end) + api.nvim_win_close(win, true) + assert_alive() + end) + it(':sleep cursor placement #22639', function() local float_opts = { relative = 'editor', row = 1, col = 1, width = 4, height = 3 } local win = api.nvim_open_win(api.nvim_create_buf(false, false), true, float_opts)