fix(swapfile): don't use uninitialized memory (#35813)

Also add a test for #35802.
This commit is contained in:
zeertzjq
2025-09-17 11:36:27 +08:00
committed by GitHub
parent 8ec562fe52
commit 63ece2b151
2 changed files with 44 additions and 7 deletions

View File

@@ -1403,8 +1403,8 @@ int recover_names(char *fname, bool do_list, list_T *ret_list, int nr, char **fn
StringBuilder msg = KV_INITIAL_VALUE;
kv_resize(msg, IOSIZE);
swapfile_info(files[i], &msg);
bool need_clear;
msg_multiline(cstr_as_string(msg.items), 0, false, false, &need_clear);
bool need_clear = false;
msg_multiline(cbuf_as_string(msg.items, msg.size), 0, false, false, &need_clear);
kv_destroy(msg);
}
} else {
@@ -3569,8 +3569,8 @@ static char *findswapname(buf_T *buf, char **dirp, char *old_fname, bool *found_
// pretend screen didn't scroll, need redraw anyway
msg_reset_scroll();
} else {
bool need_clear;
msg_multiline(cstr_as_string(msg.items), 0, false, false, &need_clear);
bool need_clear = false;
msg_multiline(cbuf_as_string(msg.items, msg.size), 0, false, false, &need_clear);
}
no_wait_return--;
kv_destroy(msg);

View File

@@ -9,6 +9,7 @@ local clear = n.clear
local command = n.command
local feed = n.feed
local fn = n.fn
local neq = t.neq
local nvim_prog = n.nvim_prog
local ok = t.ok
local rmdir = n.rmdir
@@ -51,7 +52,7 @@ describe("preserve and (R)ecover with custom 'directory'", function()
set swapfile fileformat=unix undolevels=-1
]]
local nvim0
local nvim0 --- @type test.Session
before_each(function()
nvim0 = n.new_session(false)
set_session(nvim0)
@@ -63,12 +64,13 @@ describe("preserve and (R)ecover with custom 'directory'", function()
rmdir(swapdir)
end)
--- @return string
local function setup_swapname()
exec(init)
command('edit! ' .. testfile)
feed('isometext<esc>')
exec('redir => g:swapname | silent swapname | redir END')
return eval('g:swapname')
return eval('g:swapname'):match('[^\n]*$')
end
local function test_recover(swappath1)
@@ -99,6 +101,7 @@ describe("preserve and (R)ecover with custom 'directory'", function()
it('with :preserve and SIGKILL', function()
local swappath1 = setup_swapname()
command('preserve')
neq(nil, uv.fs_stat(swappath1))
eq(0, vim.uv.kill(eval('getpid()'), 'sigkill'))
test_recover(swappath1)
end)
@@ -106,6 +109,7 @@ describe("preserve and (R)ecover with custom 'directory'", function()
it('closing stdio channel without :preserve #22096', function()
local swappath1 = setup_swapname()
nvim0:close()
neq(nil, uv.fs_stat(swappath1))
test_recover(swappath1)
end)
@@ -124,13 +128,46 @@ describe("preserve and (R)ecover with custom 'directory'", function()
set_session(nvim0)
command('call chanclose(&channel)') -- Kill the child process.
screen0:expect({ any = pesc('[Process exited 1]') }) -- Wait for the child process to stop.
neq(nil, uv.fs_stat(swappath1))
test_recover(swappath1)
end)
it('manual :recover with multiple swapfiles', function()
local swappath1 = setup_swapname()
eq('.swp', swappath1:match('%.[^.]+$'))
nvim0:close()
neq(nil, uv.fs_stat(swappath1))
local swappath2 = swappath1:gsub('%.swp$', '.swo')
eq(true, uv.fs_copyfile(swappath1, swappath2))
clear()
exec(init)
local screen = Screen.new(256, 40)
feed(':recover! ' .. testfile .. '<CR>')
screen:expect({
any = {
'\nSwap files found:',
'\n In directory ',
vim.pesc('\n1. '),
vim.pesc('\n2. '),
vim.pesc('\nEnter number of swap file to use (0 to quit): ^'),
},
none = vim.pesc('{18:^@}'),
})
feed('2<CR>')
screen:expect({
any = {
vim.pesc('\nRecovery completed.'),
vim.pesc('\n{6:Press ENTER or type command to continue}^'),
},
})
feed('<CR>')
expect('sometext')
end)
end)
describe('swapfile detection', function()
local swapdir = uv.cwd() .. '/Xtest_swapdialog_dir'
local nvim0
local nvim0 --- @type test.Session
-- Put swapdir at the start of the 'directory' list. #1836
-- Note: `set swapfile` *must* go after `set directory`: otherwise it may
-- attempt to create a swapfile in different directory.