From a9ffdca528d132c0a9016495c2e62eb1d4563bfc Mon Sep 17 00:00:00 2001 From: Sean Dewar <6256228+seandewar@users.noreply.github.com> Date: Wed, 17 Dec 2025 17:57:30 +0000 Subject: [PATCH] fix(api): open_win leak from naughty autocommands Problem: error set by win_set_buf may leak if autocommands immediately close the new window. Solution: free the error set by win_set_buf. (prefer nvim_open_win's error as it's more important and will cause 0 to be returned) --- src/nvim/api/win_config.c | 1 + test/functional/api/window_spec.lua | 25 +++++++++++++++++++++++++ 2 files changed, 26 insertions(+) diff --git a/src/nvim/api/win_config.c b/src/nvim/api/win_config.c index b7a00adbc8..2af6e56a3d 100644 --- a/src/nvim/api/win_config.c +++ b/src/nvim/api/win_config.c @@ -343,6 +343,7 @@ Window nvim_open_win(Buffer buffer, Boolean enter, Dict(win_config) *config, Err } } if (!tp) { + api_clear_error(err); // may have been set by win_set_buf api_set_error(err, kErrorTypeException, "Window was closed immediately"); goto cleanup; } diff --git a/test/functional/api/window_spec.lua b/test/functional/api/window_spec.lua index 7ec2288e21..400c3611c7 100644 --- a/test/functional/api/window_spec.lua +++ b/test/functional/api/window_spec.lua @@ -2068,6 +2068,31 @@ describe('API/win', function() api.nvim_open_win(0, true, { split = 'below' }) eq(11, api.nvim_win_get_height(0)) end) + + it('no leak when win_set_buf fails and window is closed immediately', function() + -- Following used to leak. + command('autocmd BufEnter * ++once quit! | throw 1337') + eq( + 'Window was closed immediately', + pcall_err( + api.nvim_open_win, + api.nvim_create_buf(true, true), + true, + { relative = 'editor', width = 5, height = 5, row = 1, col = 1 } + ) + ) + -- If the window wasn't closed, still set errors from win_set_buf. + command('autocmd BufEnter * ++once throw 1337') + eq( + 'BufEnter Autocommands for "*": 1337', + pcall_err( + api.nvim_open_win, + api.nvim_create_buf(true, true), + true, + { relative = 'editor', width = 5, height = 5, row = 1, col = 1 } + ) + ) + end) end) describe('set_config', function()