Skip to content

Commit

Permalink
fix(api): fix crash after set_option_value_for() neovim#15390
Browse files Browse the repository at this point in the history
Problem:
This crashes Nvim:
    tabedit
    call nvim_win_set_option(1000, 'statusline', 'status')
    split
    wincmd J
    wincmd j

Solution:
- Change `no_display` parameter value to be the same as in matching
  `restore_win_noblock` call. In case of different values `topframe`
  isn't restored to `curtab->tp_topframe`.
- Call `restore_win_noblock` if `switch_win_noblock` returns `FAIL`
  (`switch_win` must always have matching `restore_win`)
- Change `switch_win`/`restore_win` to `_noblock` versions to allow
  autocommands.

fixes neovim#14097
fixes neovim#13577
  • Loading branch information
gmntroll committed Sep 26, 2021
1 parent 2f9b9e6 commit 8b0e6cc
Show file tree
Hide file tree
Showing 2 changed files with 25 additions and 9 deletions.
8 changes: 5 additions & 3 deletions src/nvim/api/private/helpers.c
Expand Up @@ -1413,8 +1413,10 @@ static void set_option_value_for(char *key, int numval, char *stringval, int opt
switch (opt_type)
{
case SREQ_WIN:
if (switch_win(&save_curwin, &save_curtab, (win_T *)from,
win_find_tabpage((win_T *)from), false) == FAIL) {
if (switch_win_noblock(&save_curwin, &save_curtab, (win_T *)from,
win_find_tabpage((win_T *)from), true)
== FAIL) {
restore_win_noblock(save_curwin, save_curtab, true);
if (try_end(err)) {
return;
}
Expand All @@ -1424,7 +1426,7 @@ static void set_option_value_for(char *key, int numval, char *stringval, int opt
return;
}
set_option_value_err(key, numval, stringval, opt_flags, err);
restore_win(save_curwin, save_curtab, true);
restore_win_noblock(save_curwin, save_curtab, true);
break;
case SREQ_BUF:
aucmd_prepbuf(&aco, (buf_T *)from);
Expand Down
26 changes: 20 additions & 6 deletions test/functional/api/window_spec.lua
@@ -1,8 +1,9 @@
local helpers = require('test.functional.helpers')(after_each)
local clear, nvim, curbuf, curbuf_contents, window, curwin, eq, neq,
ok, feed, insert, eval = helpers.clear, helpers.nvim, helpers.curbuf,
ok, feed, insert, eval, tabpage = helpers.clear, helpers.nvim, helpers.curbuf,
helpers.curbuf_contents, helpers.window, helpers.curwin, helpers.eq,
helpers.neq, helpers.ok, helpers.feed, helpers.insert, helpers.eval
helpers.neq, helpers.ok, helpers.feed, helpers.insert, helpers.eval,
helpers.tabpage
local poke_eventloop = helpers.poke_eventloop
local curwinmeths = helpers.curwinmeths
local funcs = helpers.funcs
Expand All @@ -11,6 +12,7 @@ local NIL = helpers.NIL
local meths = helpers.meths
local command = helpers.command
local pcall_err = helpers.pcall_err
local assert_alive = helpers.assert_alive

-- check if str is visible at the beginning of some line
local function is_visible(str)
Expand Down Expand Up @@ -206,7 +208,7 @@ describe('API/win', function()
end)
end)

describe('{get,set}_option', function()
describe('nvim_win_get_option, nvim_win_set_option', function()
it('works', function()
curwin('set_option', 'colorcolumn', '4,3')
eq('4,3', curwin('get_option', 'colorcolumn'))
Expand All @@ -224,6 +226,18 @@ describe('API/win', function()
pcall_err(curwin, 'get_option', 'statusline'))
eq('', eval('&l:statusline')) -- confirm local value was not copied
end)

it('after switching windows #15390', function()
nvim('command', 'tabnew')
local tab1 = unpack(nvim('list_tabpages'))
local win1 = unpack(tabpage('list_wins', tab1))
window('set_option', win1, 'statusline', 'window-status')
nvim('command', 'split')
nvim('command', 'wincmd J')
nvim('command', 'wincmd j')
eq('window-status', window('get_option', win1, 'statusline'))
assert_alive()
end)
end)

describe('get_position', function()
Expand Down Expand Up @@ -354,13 +368,13 @@ describe('API/win', function()
local win = meths.open_win(0, true, {
relative='editor', row=10, col=10, width=50, height=10
})
local tabpage = eval('tabpagenr()')
local tab = eval('tabpagenr()')
command('tabprevious')
eq(1, eval('tabpagenr()'))
meths.win_close(win, false)

eq(1001, meths.tabpage_get_win(tabpage).id)
helpers.assert_alive()
eq(1001, meths.tabpage_get_win(tab).id)
assert_alive()
end)
end)

Expand Down

0 comments on commit 8b0e6cc

Please sign in to comment.