neovim

Neovim text editor
git clone https://git.dasho.dev/neovim.git
Log | Files | Refs | README

commit a2070ba8773ca264f68a4cfb50cb3d12219838e7
parent be5cf338362244a944cdeebf07520f85d7d93226
Author: zeertzjq <zeertzjq@outlook.com>
Date:   Tue, 30 Jan 2024 07:34:37 +0800

vim-patch:9.1.0065: Segfault with CompleteChanged autocommand (#27261)

Problem:  Segfault with CompleteChanged autocommand
          (markonm )
Solution: Test match->cp_prev for being NULL before accessing it

closes: vim/vim#13929

https://github.com/vim/vim/commit/fef66301665027f1801a18d796f74584666f41ef

Co-authored-by: Christian Brabandt <cb@256bit.org>
Diffstat:
Msrc/nvim/insexpand.c | 8+++++---
Mtest/functional/editor/completion_spec.lua | 21+++++++++++++++++++--
Mtest/old/testdir/test_ins_complete.vim | 16+++++++++++++++-
3 files changed, 39 insertions(+), 6 deletions(-)

diff --git a/src/nvim/insexpand.c b/src/nvim/insexpand.c @@ -2760,9 +2760,11 @@ static int info_add_completion_info(list_T *li) // Skip the element with the CP_ORIGINAL_TEXT flag at the beginning, in case of // forward completion, or at the end, in case of backward completion. - match = forward ? match->cp_next - : (compl_no_select && match_at_original_text(match) - ? match->cp_prev : match->cp_prev->cp_prev); + match = (forward || match->cp_prev == NULL + ? match->cp_next + : (compl_no_select && match_at_original_text(match) + ? match->cp_prev + : match->cp_prev->cp_prev)); while (match != NULL && !match_at_original_text(match)) { dict_T *di = tv_dict_alloc(); diff --git a/test/functional/editor/completion_spec.lua b/test/functional/editor/completion_spec.lua @@ -1078,7 +1078,24 @@ describe('completion', function() ]]) end) - it('does not crash if text is changed by first call to complete function #17489', function() + -- oldtest: Test_complete_changed_complete_info() + it('no crash calling complete_info() in CompleteChanged', function() + source([[ + set completeopt=menuone + autocmd CompleteChanged * call complete_info(['items']) + call feedkeys("iii\<cr>\<c-p>") + ]]) + screen:expect([[ + ii | + ii^ | + {2:ii }{0: }| + {0:~ }|*4 + {3:-- Keyword completion (^N^P) The only match} | + ]]) + assert_alive() + end) + + it('no crash if text changed by first call to complete function #17489', function() source([[ func Complete(findstart, base) abort if a:findstart @@ -1097,7 +1114,7 @@ describe('completion', function() assert_alive() end) - it('does not crash when using i_CTRL-X_CTRL-V to complete non-existent colorscheme', function() + it('no crash using i_CTRL-X_CTRL-V to complete non-existent colorscheme', function() feed('icolorscheme NOSUCHCOLORSCHEME<C-X><C-V>') expect('colorscheme NOSUCHCOLORSCHEME') assert_alive() diff --git a/test/old/testdir/test_ins_complete.vim b/test/old/testdir/test_ins_complete.vim @@ -2407,4 +2407,18 @@ func Test_complete_info_index() bwipe! endfunc -" vim: shiftwidth=2 sts=2 expandtab +func Test_complete_changed_complete_info() + CheckRunVimInTerminal + " this used to crash vim, see #13929 + let lines =<< trim END + set completeopt=menuone + autocmd CompleteChanged * call complete_info(['items']) + call feedkeys("iii\<cr>\<c-p>") + END + call writefile(lines, 'Xsegfault', 'D') + let buf = RunVimInTerminal('-S Xsegfault', #{rows: 5}) + call WaitForAssert({-> assert_match('^ii', term_getline(buf, 1))}, 1000) + call StopVimInTerminal(buf) +endfunc + +" vim: shiftwidth=2 sts=2 expandtab nofoldenable