fix(terminal): heap UAF from autocmds when entering #38316

Problem: heap-use-after-free possible when entering Terminal mode if
autocommands close the terminal.

Solution: set the refcount. Skip to the end if we must close the terminal.
This commit is contained in:
Sean Dewar
2026-03-15 21:38:25 +00:00
committed by GitHub
parent 0ca9849387
commit 1c57e4cb4f
2 changed files with 20 additions and 4 deletions

View File

@@ -943,12 +943,18 @@ bool terminal_enter(void)
// Don't fire TextChangedT from changes in Normal mode.
curbuf->b_last_changedtick_i = buf_get_changedtick(curbuf);
// Don't let autocommands free the terminal now!
s->term->refcount++;
apply_autocmds(EVENT_TERMENTER, NULL, NULL, false, curbuf);
may_trigger_modechanged();
s->state.execute = terminal_execute;
s->state.check = terminal_check;
state_enter(&s->state);
s->term->refcount--;
if (s->term->buf_handle == 0) {
s->close = true; // skip entering and close
} else {
s->state.execute = terminal_execute;
s->state.check = terminal_check;
state_enter(&s->state);
}
if (!s->got_bsl_o) {
restart_edit = 0;

View File

@@ -1146,6 +1146,16 @@ describe(':terminal buffer', function()
eq(false, api.nvim_buf_is_valid(term_buf))
end)
it('no heap-use-after-free from autocmds when entering terminal mode', function()
local chans = api.nvim_list_chans()
local buf = api.nvim_get_current_buf()
api.nvim_open_term(0, {})
command('autocmd TermEnter,ModeChanged * ++once bwipeout!')
feed('i')
eq(false, api.nvim_buf_is_valid(buf))
eq(chans, api.nvim_list_chans())
end)
local enew_screen = [[
^ |
{1:~ }|*5