fix(api): LuaRef leak in nvim_set_keymap on LHS too long (>=66 bytes) #39351

Problem: `nvim_set_keymap` leaks the `callback` `LuaRef` when the
LHS is too long.

Solution: Make `set_maparg_lhs_rhs` transfer `rhs_lua` to
`MapArguments` up front so the caller always owns the ref.
This commit is contained in:
Barrett Ruth
2026-04-24 14:10:28 -04:00
committed by GitHub
parent f130922744
commit 58aad59e1c
2 changed files with 18 additions and 0 deletions

View File

@@ -302,6 +302,7 @@ static bool set_maparg_lhs_rhs(const char *const orig_lhs, const size_t orig_lhs
const LuaRef rhs_lua, const char *const cpo_val,
MapArguments *const mapargs)
{
mapargs->rhs_lua = rhs_lua;
char lhs_buf[128];
// If mapping has been given as ^V<C_UP> say, then replace the term codes

View File

@@ -617,6 +617,23 @@ describe('nvim_set_keymap, nvim_del_keymap', function()
eq('LHS exceeds maximum map length: ' .. lhs, pcall_err(api.nvim_del_keymap, '', lhs))
end)
it('does not leak callback LuaRef on too-long LHS #39351', function()
eq(
0,
exec_lua(function()
local weak = setmetatable({}, { __mode = 'v' })
for i = 1, 2 do
local cb = function() end
weak[i] = cb
local ok = pcall(vim.api.nvim_set_keymap, 'n', ('a'):rep(66), '', { callback = cb })
assert(not ok)
end
collectgarbage('collect')
return vim.tbl_count(weak)
end)
)
end)
it('does not throw errors when rhs is longer than MAXMAPLEN', function()
local MAXMAPLEN = 50
local rhs = ''