commit 1b627f6c59999b550b2b312bcba482c6f75dc694
parent 7ee41a4b33c080b9bd29eef7a9fb57715f4c97e9
Author: Sean Dewar <6256228+seandewar@users.noreply.github.com>
Date: Mon, 9 Feb 2026 12:51:04 +0000
fix(terminal): set b_locked when setting &buftype (#37787)
Problem: heap use-after-free if OptionSet autocommands from setting a terminal's
&buftype wipe the buffer.
Solution: set b_locked during OptionSet for &buftype.
Diffstat:
2 files changed, 8 insertions(+), 1 deletion(-)
diff --git a/src/nvim/terminal.c b/src/nvim/terminal.c
@@ -580,7 +580,9 @@ void terminal_open(Terminal **termpp, buf_T *buf)
assert(term->invalid_start >= 0);
}
refresh_screen(term, buf);
+ buf->b_locked++;
set_option_value(kOptBuftype, STATIC_CSTR_AS_OPTVAL("terminal"), OPT_LOCAL);
+ buf->b_locked--;
if (buf->b_ffname != NULL) {
buf_set_term_title(buf, buf->b_ffname, strlen(buf->b_ffname));
diff --git a/test/functional/terminal/buffer_spec.lua b/test/functional/terminal/buffer_spec.lua
@@ -1165,8 +1165,13 @@ describe(':terminal buffer', function()
eq({ mode = 'nt', blocking = false }, api.nvim_get_mode())
end)
- it('does not allow b:term_title watcher to delete buffer', function()
+ it('does not allow OptionSet or b:term_title watcher to delete buffer', function()
+ local au = api.nvim_create_autocmd('OptionSet', { command = 'bwipeout!' })
local chan = api.nvim_open_term(0, {})
+ matches('^E937: ', api.nvim_get_vvar('errmsg'))
+ api.nvim_del_autocmd(au)
+ api.nvim_set_vvar('errmsg', '')
+
api.nvim_chan_send(chan, '\027]2;SOME_TITLE\007')
eq('SOME_TITLE', api.nvim_buf_get_var(0, 'term_title'))
command([[call dictwatcheradd(b:, 'term_title', {-> execute('bwipe!')})]])