neovim

Neovim text editor
git clone https://git.dasho.dev/neovim.git
Log | Files | Refs | README

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:
Msrc/nvim/terminal.c | 2++
Mtest/functional/terminal/buffer_spec.lua | 7++++++-
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!')})]])