mirror of
https://github.com/neovim/neovim.git
synced 2026-07-31 04:39:07 +00:00
vim-patch:9.2.0845: [security]: arbitrary Ex command execution during C omni-completion
Problem: [security]: arbitrary Ex command execution during C
omni-completion (Threonine)
Solution: Match tags typeref literally to block Ex command injection
(Yasuhiro Matsumoto).
Escaping only "/" and "\" left the typeref able to break out of the
:vimgrep pattern without a "/": an unclosed "[" makes vimgrep's pattern
skipping fail, and the parser then treats a following "|" as a command
separator, so the tag value runs as Ex commands during C omni-completion.
Match the field literally with \V so no regex metacharacter can affect
pattern parsing.
Github Security Advisory:
https://github.com/vim/vim/security/advisories/GHSA-cx73-phcg-3j5g
2f628d8104
Co-authored-by: Yasuhiro Matsumoto <mattn.jp@gmail.com>
This commit is contained in:
@@ -555,8 +555,11 @@ func s:StructMembers(typename, items, all)
|
||||
if complete_check()
|
||||
return []
|
||||
endif
|
||||
" Match "typename" literally (\V): escaping alone is not enough, as e.g.
|
||||
" an unclosed "[" makes vimgrep's pattern skipping fail and the rest of
|
||||
" the tag value is then parsed as Ex commands.
|
||||
exe 'silent! keepj noautocmd '
|
||||
\ .. n .. 'vimgrep /\t' .. escape(typename, '/\') .. '\(\t\|$\)/j '
|
||||
\ .. n .. 'vimgrep /\t\V' .. escape(typename, '/\') .. '\m\(\t\|$\)/j '
|
||||
\ .. fnames
|
||||
|
||||
let qflist = getqflist()
|
||||
|
||||
@@ -31,6 +31,32 @@ func Test_ccomplete_no_exec_via_typeref()
|
||||
unlet! g:ccomplete_injected
|
||||
endfunc
|
||||
|
||||
" Escaping "/" and "\" is not enough: with no "/" in the payload, an unclosed
|
||||
" "[" makes vimgrep's pattern skipping fail, and the command parser then treats
|
||||
" the first "|" as a command separator. The typeref must be matched literally.
|
||||
func Test_ccomplete_no_exec_via_typeref_bracket()
|
||||
CheckUnix
|
||||
let sentinel = tempname()
|
||||
call delete(sentinel)
|
||||
let tagsfile = s:WriteTags([
|
||||
\ "myvar\tmain.c\t/^x$/;\"\tv\ttyperef:struct:[|call system('touch " .. sentinel .. "')|####",
|
||||
\ ])
|
||||
|
||||
let save_tags = &tags
|
||||
let &tags = tagsfile
|
||||
|
||||
new
|
||||
call ccomplete#Complete(1, '')
|
||||
call ccomplete#Complete(0, 'myvar.x')
|
||||
|
||||
call assert_false(filereadable(sentinel),
|
||||
\ 'typeref field was executed as an Ex command during omni-completion')
|
||||
|
||||
bwipe!
|
||||
let &tags = save_tags
|
||||
call delete(sentinel)
|
||||
endfunc
|
||||
|
||||
" A legitimate typeref must still drive struct-member completion: escaping the
|
||||
" field value must not break the normal path.
|
||||
func Test_ccomplete_typeref_completion_still_works()
|
||||
|
||||
Reference in New Issue
Block a user