fix(messages)!: vim.ui_attach message callbacks are unsafe

Problem:  Lua callbacks for "msg_show" events with vim.ui_attach() are
          executed when it is not safe.
Solution: Disallow non-fast API calls for "msg_show" event callbacks.
          Automatically detach callback after excessive errors.
          Make sure fast APIs do not modify Nvim state.
This commit is contained in:
Luuk van Baal
2024-06-20 14:48:06 +02:00
parent 7d771c3eee
commit de48fbbd5f
17 changed files with 215 additions and 141 deletions

View File

@@ -25,8 +25,6 @@ local command = n.command
local write_file = t.write_file
local api = n.api
local sleep = vim.uv.sleep
local matches = t.matches
local pcall_err = t.pcall_err
local assert_alive = n.assert_alive
local poke_eventloop = n.poke_eventloop
local feed = n.feed
@@ -227,72 +225,6 @@ describe('listing functions using :function', function()
exec_capture(('function <lambda>%s'):format(num))
)
end)
it('does not crash if another function is deleted while listing', function()
local _ = Screen.new(80, 24)
matches(
'Vim%(function%):E454: Function list was modified$',
pcall_err(
exec_lua,
[=[
vim.cmd([[
func Func1()
endfunc
func Func2()
endfunc
func Func3()
endfunc
]])
local ns = vim.api.nvim_create_namespace('test')
vim.ui_attach(ns, { ext_messages = true }, function(event, _, content)
if event == 'msg_show' and content[1][2] == 'function Func1()' then
vim.cmd('delfunc Func3')
end
end)
vim.cmd('function')
vim.ui_detach(ns)
]=]
)
)
assert_alive()
end)
it('does not crash if the same function is deleted while listing', function()
local _ = Screen.new(80, 24)
matches(
'Vim%(function%):E454: Function list was modified$',
pcall_err(
exec_lua,
[=[
vim.cmd([[
func Func1()
endfunc
func Func2()
endfunc
func Func3()
endfunc
]])
local ns = vim.api.nvim_create_namespace('test')
vim.ui_attach(ns, { ext_messages = true }, function(event, _, content)
if event == 'msg_show' and content[1][2] == 'function Func1()' then
vim.cmd('delfunc Func2')
end
end)
vim.cmd('function')
vim.ui_detach(ns)
]=]
)
)
assert_alive()
end)
end)
it('no double-free in garbage collection #16287', function()