neovim

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

commit 429c40cce3fce3b5391afef8208d65a80a316018
parent feba56af7d032c948a78c21735502bebe45f8361
Author: zeertzjq <zeertzjq@outlook.com>
Date:   Mon, 13 Jun 2022 06:02:00 +0800

fix(buffer): disable buffer-updates before removing from window #18933

There can be other places that access window buffer info (e.g.
`tabpagebuflist()`), so checking `w_closing` in `win_findbuf()` doesn't
solve the crash in all cases, and may also cause Nvim's behavior to
diverge from Vim.

Fix #14998
Diffstat:
Msrc/nvim/buffer.c | 8++++----
Msrc/nvim/window.c | 2+-
Mtest/functional/lua/buffer_updates_spec.lua | 11++++++++---
3 files changed, 13 insertions(+), 8 deletions(-)

diff --git a/src/nvim/buffer.c b/src/nvim/buffer.c @@ -575,6 +575,10 @@ bool close_buffer(win_T *win, buf_T *buf, int action, bool abort_if_last, bool i return false; } + // Disable buffer-updates for the current buffer. + // No need to check `unload_buf`: in that case the function returned above. + buf_updates_unload(buf, false); + if (win != NULL // Avoid bogus clang warning. && win_valid_any_tab(win) && win->w_buffer == buf) { @@ -587,10 +591,6 @@ bool close_buffer(win_T *win, buf_T *buf, int action, bool abort_if_last, bool i buf->b_nwindows--; } - // Disable buffer-updates for the current buffer. - // No need to check `unload_buf`: in that case the function returned above. - buf_updates_unload(buf, false); - // Remove the buffer from the list. if (wipe_buf) { // Do not wipe out the buffer if it is used in a window. diff --git a/src/nvim/window.c b/src/nvim/window.c @@ -7297,7 +7297,7 @@ void win_findbuf(typval_T *argvars, list_T *list) int bufnr = tv_get_number(&argvars[0]); FOR_ALL_TAB_WINDOWS(tp, wp) { - if (!wp->w_closing && wp->w_buffer->b_fnum == bufnr) { + if (wp->w_buffer->b_fnum == bufnr) { tv_list_append_number(list, wp->handle); } } diff --git a/test/functional/lua/buffer_updates_spec.lua b/test/functional/lua/buffer_updates_spec.lua @@ -252,9 +252,8 @@ describe('lua buffer event callbacks: on_lines', function() eq(2, meths.win_get_cursor(0)[1]) end) - it('does not SEGFAULT when calling win_findbuf in on_detach', function() - - exec_lua[[ + it('does not SEGFAULT when accessing window buffer info in on_detach #14998', function() + local code = [[ local buf = vim.api.nvim_create_buf(false, false) vim.cmd"split" @@ -262,13 +261,19 @@ describe('lua buffer event callbacks: on_lines', function() vim.api.nvim_buf_attach(buf, false, { on_detach = function(_, buf) + vim.fn.tabpagebuflist() vim.fn.win_findbuf(buf) end }) ]] + exec_lua(code) command("q!") helpers.assert_alive() + + exec_lua(code) + command("bd!") + helpers.assert_alive() end) it('#12718 lnume', function()