aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/nvim/api/win_config.c6
-rw-r--r--test/functional/api/window_spec.lua8
2 files changed, 13 insertions, 1 deletions
diff --git a/src/nvim/api/win_config.c b/src/nvim/api/win_config.c
index 238ec5df1e..3959e74af9 100644
--- a/src/nvim/api/win_config.c
+++ b/src/nvim/api/win_config.c
@@ -12,6 +12,7 @@
#include "nvim/ascii_defs.h"
#include "nvim/autocmd.h"
#include "nvim/autocmd_defs.h"
+#include "nvim/buffer.h"
#include "nvim/buffer_defs.h"
#include "nvim/decoration.h"
#include "nvim/decoration_defs.h"
@@ -279,6 +280,9 @@ Window nvim_open_win(Buffer buffer, Boolean enter, Dict(win_config) *config, Err
// Autocommands may close `wp` or move it to another tabpage, so update and check `tp` after each
// event. In each case, `wp` should already be valid in `tp`, so switch_win should not fail.
+ // Also, autocommands may free the `buf` to switch to, so store a bufref to check.
+ bufref_T bufref;
+ set_bufref(&bufref, buf);
switchwin_T switchwin;
{
const int result = switch_win_noblock(&switchwin, wp, tp, true);
@@ -293,7 +297,7 @@ Window nvim_open_win(Buffer buffer, Boolean enter, Dict(win_config) *config, Err
goto_tabpage_win(tp, wp);
tp = win_find_tabpage(wp);
}
- if (tp && buf != wp->w_buffer) {
+ if (tp && bufref_valid(&bufref) && buf != wp->w_buffer) {
const bool noautocmd = curwin != wp || fconfig.noautocmd;
win_set_buf(wp, buf, noautocmd, err);
if (!noautocmd) {
diff --git a/test/functional/api/window_spec.lua b/test/functional/api/window_spec.lua
index e0cb66de41..2f6a02b5d5 100644
--- a/test/functional/api/window_spec.lua
+++ b/test/functional/api/window_spec.lua
@@ -1581,6 +1581,14 @@ describe('API/win', function()
api.nvim_open_win(api.nvim_create_buf(true, true), false, { split = 'left' })
eq(true, eval('fired'))
end)
+
+ it('no heap-use-after-free if target buffer deleted by autocommands', function()
+ local cur_buf = api.nvim_get_current_buf()
+ local new_buf = api.nvim_create_buf(true, true)
+ command('autocmd WinNew * ++once call nvim_buf_delete(' .. new_buf .. ', #{force: 1})')
+ api.nvim_open_win(new_buf, true, { split = 'left' })
+ eq(cur_buf, api.nvim_get_current_buf())
+ end)
end)
describe('set_config', function()