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.
This commit is contained in:
phanium
2026-07-15 19:48:34 +08:00
committed by GitHub
parent 44d5593afd
commit 6f370f34f2
2 changed files with 18 additions and 0 deletions

View File

@@ -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);

View File

@@ -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)