fix(api): avoid open_win UAF if target buf deleted by autocmds

Problem: WinNew and win_enter autocommands can delete the target buffer to
switch to, causing a heap-use-after-free.

Solution: store a bufref to the buffer, check it before attempting to switch.
This commit is contained in:
Sean Dewar
2024-02-11 20:15:47 +00:00
committed by Sean Dewar
parent e55a502ed4
commit b1e24f240b
2 changed files with 13 additions and 1 deletions

View File

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