Mercurial > vim
view src/testdir/test_cmdwin.vim @ 34074:1629cc65d78d v9.1.0006
patch 9.1.0006: is*() and to*() function may be unsafe
Commit: https://github.com/vim/vim/commit/184f71cc6868a240dc872ed2852542bbc1d43e28
Author: Keith Thompson <Keith.S.Thompson@gmail.com>
Date: Thu Jan 4 21:19:04 2024 +0100
patch 9.1.0006: is*() and to*() function may be unsafe
Problem: is*() and to*() function may be unsafe
Solution: Add SAFE_* macros and start using those instead
(Keith Thompson)
Use SAFE_() macros for is*() and to*() functions
The standard is*() and to*() functions declared in <ctype.h> have
undefined behavior for negative arguments other than EOF. If plain char
is signed, passing an unchecked value from argv for from user input
to one of these functions has undefined behavior.
Solution: Add SAFE_*() macros that cast the argument to unsigned char.
Most implementations behave sanely for negative arguments, and most
character values in practice are non-negative, but it's still best
to avoid undefined behavior.
The change from #13347 has been omitted, as this has already been
separately fixed in commit ac709e2fc0db6d31abb7da96f743c40956b60c3a
(v9.0.2054)
fixes: #13332
closes: #13347
Signed-off-by: Keith Thompson <Keith.S.Thompson@gmail.com>
Signed-off-by: Christian Brabandt <cb@256bit.org>
author | Christian Brabandt <cb@256bit.org> |
---|---|
date | Thu, 04 Jan 2024 21:30:04 +0100 |
parents | 7c4ad06d80ec |
children | a522c6c0127b |
line wrap: on
line source
" Tests for editing the command line. source check.vim source screendump.vim func Test_getcmdwintype() call feedkeys("q/:let a = getcmdwintype()\<CR>:q\<CR>", 'x!') call assert_equal('/', a) call feedkeys("q?:let a = getcmdwintype()\<CR>:q\<CR>", 'x!') call assert_equal('?', a) call feedkeys("q::let a = getcmdwintype()\<CR>:q\<CR>", 'x!') call assert_equal(':', a) call feedkeys(":\<C-F>:let a = getcmdwintype()\<CR>:q\<CR>", 'x!') call assert_equal(':', a) call assert_equal('', getcmdwintype()) endfunc func Test_getcmdwin_autocmd() let s:seq = [] augroup CmdWin au WinEnter * call add(s:seq, 'WinEnter ' .. win_getid()) au WinLeave * call add(s:seq, 'WinLeave ' .. win_getid()) au BufEnter * call add(s:seq, 'BufEnter ' .. bufnr()) au BufLeave * call add(s:seq, 'BufLeave ' .. bufnr()) au CmdWinEnter * call add(s:seq, 'CmdWinEnter ' .. win_getid()) au CmdWinLeave * call add(s:seq, 'CmdWinLeave ' .. win_getid()) let org_winid = win_getid() let org_bufnr = bufnr() call feedkeys("q::let a = getcmdwintype()\<CR>:let s:cmd_winid = win_getid()\<CR>:let s:cmd_bufnr = bufnr()\<CR>:q\<CR>", 'x!') call assert_equal(':', a) call assert_equal([ \ 'WinLeave ' .. org_winid, \ 'WinEnter ' .. s:cmd_winid, \ 'BufLeave ' .. org_bufnr, \ 'BufEnter ' .. s:cmd_bufnr, \ 'CmdWinEnter ' .. s:cmd_winid, \ 'CmdWinLeave ' .. s:cmd_winid, \ 'BufLeave ' .. s:cmd_bufnr, \ 'WinLeave ' .. s:cmd_winid, \ 'WinEnter ' .. org_winid, \ 'BufEnter ' .. org_bufnr, \ ], s:seq) au! augroup END endfunc func Test_cmdwin_bug() let winid = win_getid() sp try call feedkeys("q::call win_gotoid(" .. winid .. ")\<CR>:q\<CR>", 'x!') catch /^Vim\%((\a\+)\)\=:E11/ endtry bw! endfunc func Test_cmdwin_restore() CheckScreendump let lines =<< trim [SCRIPT] augroup vimHints | au! | augroup END call setline(1, range(30)) 2split [SCRIPT] call writefile(lines, 'XTest_restore', 'D') let buf = RunVimInTerminal('-S XTest_restore', {'rows': 12}) call term_sendkeys(buf, "q:") call VerifyScreenDump(buf, 'Test_cmdwin_restore_1', {}) " normal restore call term_sendkeys(buf, ":q\<CR>") call VerifyScreenDump(buf, 'Test_cmdwin_restore_2', {}) " restore after setting 'lines' with one window call term_sendkeys(buf, ":close\<CR>") call term_sendkeys(buf, "q:") call term_sendkeys(buf, ":set lines=18\<CR>") call term_sendkeys(buf, ":q\<CR>") call VerifyScreenDump(buf, 'Test_cmdwin_restore_3', {}) " clean up call StopVimInTerminal(buf) endfunc func Test_cmdwin_no_terminal() CheckScreendump let buf = RunVimInTerminal('', {'rows': 12}) call term_sendkeys(buf, ":set cmdheight=2\<CR>") call term_sendkeys(buf, "q:") call term_sendkeys(buf, ":let buf = term_start(['/bin/echo'], #{hidden: 1})\<CR>") call VerifyScreenDump(buf, 'Test_cmdwin_no_terminal', {}) call term_sendkeys(buf, ":q\<CR>") call StopVimInTerminal(buf) endfunc func Test_cmdwin_wrong_command() CheckScreendump let buf = RunVimInTerminal('', {'rows': 12}) call term_sendkeys(buf, "q:") call term_sendkeys(buf, "als\<Esc>") call term_sendkeys(buf, "\<C-W>k") call VerifyScreenDump(buf, 'Test_cmdwin_wrong_command_1', {}) call term_sendkeys(buf, "\<C-C>") call VerifyScreenDump(buf, 'Test_cmdwin_wrong_command_2', {}) call term_sendkeys(buf, ":q\<CR>") call StopVimInTerminal(buf) endfunc func Test_cmdwin_feedkeys() " This should not generate E488 call feedkeys("q:\<CR>", 'x') " Using feedkeys with q: only should automatically close the cmd window call feedkeys('q:', 'xt') call assert_equal(1, winnr('$')) call assert_equal('', getcmdwintype()) endfunc " Tests for the issues fixed in 7.4.441. " When 'cedit' is set to Ctrl-C, opening the command window hangs Vim func Test_cmdwin_cedit() exe "set cedit=\<C-c>" normal! : call assert_equal(1, winnr('$')) let g:cmd_wintype = '' func CmdWinType() let g:cmd_wintype = getcmdwintype() let g:wintype = win_gettype() return '' endfunc call feedkeys("\<C-c>a\<C-R>=CmdWinType()\<CR>\<CR>") echo input('') call assert_equal('@', g:cmd_wintype) call assert_equal('command', g:wintype) set cedit&vim delfunc CmdWinType endfunc " Test for CmdwinEnter autocmd func Test_cmdwin_autocmd() augroup CmdWin au! autocmd BufLeave * if &buftype == '' | update | endif autocmd CmdwinEnter * startinsert augroup END call assert_fails('call feedkeys("q:xyz\<CR>", "xt")', 'E492:') call assert_equal('xyz', @:) augroup CmdWin au! augroup END augroup! CmdWin endfunc func Test_cmdwin_jump_to_win() call assert_fails('call feedkeys("q:\<C-W>\<C-W>\<CR>", "xt")', 'E11:') new set modified call assert_fails('call feedkeys("q/:qall\<CR>", "xt")', ['E37:', 'E162:']) close! call feedkeys("q/:close\<CR>", "xt") call assert_equal(1, winnr('$')) call feedkeys("q/:exit\<CR>", "xt") call assert_equal(1, winnr('$')) " opening command window twice should fail call assert_beeps('call feedkeys("q:q:\<CR>\<CR>", "xt")') call assert_equal(1, winnr('$')) endfunc func Test_cmdwin_tabpage() tabedit call assert_fails("silent norm q/g :I\<Esc>", 'E11:') tabclose! endfunc func Test_cmdwin_interrupted() CheckScreendump " aborting the :smile output caused the cmdline window to use the current " buffer. let lines =<< trim [SCRIPT] au WinNew * smile [SCRIPT] call writefile(lines, 'XTest_cmdwin', 'D') let buf = RunVimInTerminal('-S XTest_cmdwin', {'rows': 18}) " open cmdwin call term_sendkeys(buf, "q:") call WaitForAssert({-> assert_match('-- More --', term_getline(buf, 18))}) " quit more prompt for :smile command call term_sendkeys(buf, "q") call WaitForAssert({-> assert_match('^$', term_getline(buf, 18))}) " execute a simple command call term_sendkeys(buf, "aecho 'done'\<CR>") call VerifyScreenDump(buf, 'Test_cmdwin_interrupted', {}) " clean up call StopVimInTerminal(buf) endfunc " Test for recursively getting multiple command line inputs func Test_cmdwin_multi_input() call feedkeys(":\<C-R>=input('P: ')\<CR>\"cyan\<CR>\<CR>", 'xt') call assert_equal('"cyan', @:) endfunc " Test for normal mode commands not supported in the cmd window func Test_cmdwin_blocked_commands() call assert_fails('call feedkeys("q:\<C-T>\<CR>", "xt")', 'E11:') call assert_fails('call feedkeys("q:\<C-]>\<CR>", "xt")', 'E11:') call assert_fails('call feedkeys("q:\<C-^>\<CR>", "xt")', 'E11:') call assert_fails('call feedkeys("q:Q\<CR>", "xt")', 'E11:') call assert_fails('call feedkeys("q:Z\<CR>", "xt")', 'E11:') call assert_fails('call feedkeys("q:\<F1>\<CR>", "xt")', 'E11:') call assert_fails('call feedkeys("q:\<C-W>s\<CR>", "xt")', 'E11:') call assert_fails('call feedkeys("q:\<C-W>v\<CR>", "xt")', 'E11:') call assert_fails('call feedkeys("q:\<C-W>^\<CR>", "xt")', 'E11:') call assert_fails('call feedkeys("q:\<C-W>n\<CR>", "xt")', 'E11:') call assert_fails('call feedkeys("q:\<C-W>z\<CR>", "xt")', 'E11:') call assert_fails('call feedkeys("q:\<C-W>o\<CR>", "xt")', 'E11:') call assert_fails('call feedkeys("q:\<C-W>w\<CR>", "xt")', 'E11:') call assert_fails('call feedkeys("q:\<C-W>j\<CR>", "xt")', 'E11:') call assert_fails('call feedkeys("q:\<C-W>k\<CR>", "xt")', 'E11:') call assert_fails('call feedkeys("q:\<C-W>h\<CR>", "xt")', 'E11:') call assert_fails('call feedkeys("q:\<C-W>l\<CR>", "xt")', 'E11:') call assert_fails('call feedkeys("q:\<C-W>T\<CR>", "xt")', 'E11:') call assert_fails('call feedkeys("q:\<C-W>x\<CR>", "xt")', 'E11:') call assert_fails('call feedkeys("q:\<C-W>r\<CR>", "xt")', 'E11:') call assert_fails('call feedkeys("q:\<C-W>R\<CR>", "xt")', 'E11:') call assert_fails('call feedkeys("q:\<C-W>K\<CR>", "xt")', 'E11:') call assert_fails('call feedkeys("q:\<C-W>}\<CR>", "xt")', 'E11:') call assert_fails('call feedkeys("q:\<C-W>]\<CR>", "xt")', 'E11:') call assert_fails('call feedkeys("q:\<C-W>f\<CR>", "xt")', 'E11:') call assert_fails('call feedkeys("q:\<C-W>d\<CR>", "xt")', 'E11:') call assert_fails('call feedkeys("q:\<C-W>g\<CR>", "xt")', 'E11:') endfunc " Close the Cmd-line window in insert mode using CTRL-C func Test_cmdwin_insert_mode_close() %bw! let s = '' exe "normal q:a\<C-C>let s='Hello'\<CR>" call assert_equal('Hello', s) call assert_equal(1, winnr('$')) endfunc func Test_cmdwin_ex_mode_with_modifier() " this was accessing memory after allocated text in Ex mode new call setline(1, ['some', 'text', 'lines']) silent! call feedkeys("gQnormal vq:atopleft\<C-V>\<CR>\<CR>", 'xt') bwipe! endfunc func s:ComplInCmdwin_GlobalCompletion(a, l, p) return 'global' endfunc func s:ComplInCmdwin_LocalCompletion(a, l, p) return 'local' endfunc func Test_compl_in_cmdwin() set wildmenu wildchar=<Tab> com! -nargs=1 -complete=command GetInput let input = <q-args> com! -buffer TestCommand echo 'TestCommand' let w:test_winvar = 'winvar' let b:test_bufvar = 'bufvar' " User-defined commands let input = '' call feedkeys("q:iGetInput T\<C-x>\<C-v>\<CR>", 'tx!') call assert_equal('TestCommand', input) let input = '' call feedkeys("q::GetInput T\<Tab>\<CR>:q\<CR>", 'tx!') call assert_equal('T', input) com! -nargs=1 -complete=var GetInput let input = <q-args> " Window-local variables let input = '' call feedkeys("q:iGetInput w:test_\<C-x>\<C-v>\<CR>", 'tx!') call assert_equal('w:test_winvar', input) let input = '' call feedkeys("q::GetInput w:test_\<Tab>\<CR>:q\<CR>", 'tx!') call assert_equal('w:test_', input) " Buffer-local variables let input = '' call feedkeys("q:iGetInput b:test_\<C-x>\<C-v>\<CR>", 'tx!') call assert_equal('b:test_bufvar', input) let input = '' call feedkeys("q::GetInput b:test_\<Tab>\<CR>:q\<CR>", 'tx!') call assert_equal('b:test_', input) " Argument completion of buffer-local command func s:ComplInCmdwin_GlobalCompletionList(a, l, p) return ['global'] endfunc func s:ComplInCmdwin_LocalCompletionList(a, l, p) return ['local'] endfunc func s:ComplInCmdwin_CheckCompletion(arg) call assert_equal('local', a:arg) endfunc com! -nargs=1 -complete=custom,<SID>ComplInCmdwin_GlobalCompletion \ TestCommand call s:ComplInCmdwin_CheckCompletion(<q-args>) com! -buffer -nargs=1 -complete=custom,<SID>ComplInCmdwin_LocalCompletion \ TestCommand call s:ComplInCmdwin_CheckCompletion(<q-args>) call feedkeys("q:iTestCommand \<Tab>\<CR>", 'tx!') com! -nargs=1 -complete=customlist,<SID>ComplInCmdwin_GlobalCompletionList \ TestCommand call s:ComplInCmdwin_CheckCompletion(<q-args>) com! -buffer -nargs=1 -complete=customlist,<SID>ComplInCmdwin_LocalCompletionList \ TestCommand call s:ComplInCmdwin_CheckCompletion(<q-args>) call feedkeys("q:iTestCommand \<Tab>\<CR>", 'tx!') func! s:ComplInCmdwin_CheckCompletion(arg) call assert_equal('global', a:arg) endfunc new call feedkeys("q:iTestCommand \<Tab>\<CR>", 'tx!') quit delfunc s:ComplInCmdwin_GlobalCompletion delfunc s:ComplInCmdwin_LocalCompletion delfunc s:ComplInCmdwin_GlobalCompletionList delfunc s:ComplInCmdwin_LocalCompletionList delfunc s:ComplInCmdwin_CheckCompletion delcom -buffer TestCommand delcom TestCommand delcom GetInput unlet w:test_winvar unlet b:test_bufvar set wildmenu& wildchar& endfunc func Test_cmdwin_cmd_completion() set wildmenu wildchar=<Tab> com! -nargs=* -complete=command SomeOne echo 'one' com! -nargs=* -complete=command SomeTwo echo 'two' call feedkeys("q:aSome\<Tab>\<Home>\"\<CR>", 'tx') call assert_equal('"SomeOne', @:) call feedkeys("q:aSome\<Tab>\<Tab>\<Home>\"\<CR>", 'tx') call assert_equal('"SomeTwo', @:) call feedkeys("q:aSome\<Tab>\<Tab>\<S-Tab>\<Home>\"\<CR>", 'tx') call assert_equal('"SomeOne', @:) delcom SomeOne delcom SomeTwo set wildmenu& wildchar& endfunc func Test_cmdwin_ctrl_bsl() " Using CTRL-\ CTRL-N in cmd window should close the window call feedkeys("q:\<C-\>\<C-N>", 'xt') call assert_equal('', getcmdwintype()) endfunc func Test_cant_open_cmdwin_in_cmdwin() try call feedkeys("q:q::q\<CR>", "x!") catch let caught = v:exception endtry call assert_match('E1292:', caught) endfunc func Test_cmdwin_virtual_edit() enew! set ve=all cpo+=$ silent normal q/s set ve= cpo-=$ endfunc " Check that a :normal command can be used to stop Visual mode without side " effects. func Test_normal_escape() call feedkeys("q:i\" foo\<Esc>:normal! \<C-V>\<Esc>\<CR>:\" bar\<CR>", 'ntx') call assert_equal('" bar', @:) endfunc " This was using a pointer to a freed buffer func Test_cmdwin_freed_buffer_ptr() " this does not work on MS-Windows because renaming an open file fails CheckNotMSWindows au BufEnter * next 0| file edit 0 silent! norm q/ au! BufEnter bwipe! endfunc " This was resulting in a window with negative width. " The test doesn't reproduce the illegal memory access though... func Test_cmdwin_split_often() let lines = &lines let columns = &columns set t_WS= try set encoding=iso8859 set ruler winsize 0 0 noremap 0 H sil norm 0000000q: catch /E36:/ endtry bwipe! set encoding=utf8 let &lines = lines let &columns = columns endfunc func Test_cmdwin_restore_heights() set showtabline=0 cmdheight=2 laststatus=0 call feedkeys("q::set cmdheight=1\<CR>:q\<CR>", 'ntx') call assert_equal(&lines - 1, winheight(0)) set showtabline=2 cmdheight=3 call feedkeys("q::set showtabline=0\<CR>:q\<CR>", 'ntx') call assert_equal(&lines - 3, winheight(0)) set cmdheight=1 laststatus=2 call feedkeys("q::set laststatus=0\<CR>:q\<CR>", 'ntx') call assert_equal(&lines - 1, winheight(0)) set laststatus=2 call feedkeys("q::set laststatus=1\<CR>:q\<CR>", 'ntx') call assert_equal(&lines - 1, winheight(0)) set laststatus=2 belowright vsplit wincmd _ let restcmds = winrestcmd() call feedkeys("q::set laststatus=1\<CR>:q\<CR>", 'ntx') " As we have 2 windows, &ls = 1 should still have a statusline on the last " window. As such, the number of available rows hasn't changed and the window " sizes should be restored. call assert_equal(restcmds, winrestcmd()) set cmdheight& showtabline& laststatus& endfunc " vim: shiftwidth=2 sts=2 expandtab