diff options
author | zeertzjq <zeertzjq@outlook.com> | 2022-11-12 09:57:29 +0800 |
---|---|---|
committer | GitHub <noreply@github.com> | 2022-11-12 09:57:29 +0800 |
commit | 2425fe2dc5e5985779912319433ddf914a20dd6a (patch) | |
tree | 94f06238405f0195241f2264dcb316c7a860acab /src | |
parent | eee956051637a5dff02ba6c6083fbffc87c0c96e (diff) | |
download | rneovim-2425fe2dc5e5985779912319433ddf914a20dd6a.tar.gz rneovim-2425fe2dc5e5985779912319433ddf914a20dd6a.tar.bz2 rneovim-2425fe2dc5e5985779912319433ddf914a20dd6a.zip |
vim-patch:8.2.2207: illegal memory access if popup menu items are changed (#21028)
Problem: Illegal memory access if popup menu items are changed while the
menu is visible. (Tomáš Janoušek)
Solution: Make a copy of the text. (closes vim/vim#7537)
https://github.com/vim/vim/commit/38455a921395a56690790c8c1d28c1c43ca04c8a
Co-authored-by: Bram Moolenaar <Bram@vim.org>
Diffstat (limited to 'src')
-rw-r--r-- | src/nvim/popupmenu.c | 13 | ||||
-rw-r--r-- | src/nvim/testdir/test_popup.vim | 28 |
2 files changed, 37 insertions, 4 deletions
diff --git a/src/nvim/popupmenu.c b/src/nvim/popupmenu.c index db22d50d66..234ce5fcba 100644 --- a/src/nvim/popupmenu.c +++ b/src/nvim/popupmenu.c @@ -1043,10 +1043,16 @@ void pum_show_popupmenu(vimmenu_T *menu) pumitem_T *array = (pumitem_T *)xcalloc((size_t)pum_size, sizeof(pumitem_T)); for (vimmenu_T *mp = menu->children; mp != NULL; mp = mp->next) { + char *s = NULL; + // Make a copy of the text, the menu may be redefined in a callback. if (menu_is_separator(mp->dname)) { - array[idx++].pum_text = (char_u *)""; + s = ""; } else if (mp->modes & mp->enabled & mode) { - array[idx++].pum_text = (char_u *)mp->dname; + s = mp->dname; + } + if (s != NULL) { + s = xstrdup(s); + array[idx++].pum_text = (char_u *)s; } } @@ -1117,6 +1123,9 @@ void pum_show_popupmenu(vimmenu_T *menu) } } + for (idx = 0; idx < pum_size; idx++) { + xfree(array[idx].pum_text); + } xfree(array); pum_undisplay(true); if (!p_mousemev) { diff --git a/src/nvim/testdir/test_popup.vim b/src/nvim/testdir/test_popup.vim index 0981329320..a9b258c5f5 100644 --- a/src/nvim/testdir/test_popup.vim +++ b/src/nvim/testdir/test_popup.vim @@ -871,18 +871,30 @@ func Test_popup_command() call assert_fails('popup Foo', 'E337:') unmenu Test.Foo + let script =<< trim END + func StartTimer() + call timer_start(100, {-> ChangeMenu()}) + endfunc + func ChangeMenu() + nunmenu PopUp.&Paste + nnoremenu 1.40 PopUp.&Paste :echomsg "pasted"<CR> + echomsg 'changed' + endfunc + END + call writefile(script, 'XtimerScript') + let lines =<< trim END one two three four five and one two Xthree four five one more two three four five END call writefile(lines, 'Xtest') - let buf = RunVimInTerminal('Xtest', {}) + let buf = RunVimInTerminal('-S XtimerScript Xtest', {}) call term_sendkeys(buf, ":source $VIMRUNTIME/menu.vim\<CR>") call term_sendkeys(buf, "/X\<CR>:popup PopUp\<CR>") call VerifyScreenDump(buf, 'Test_popup_command_01', {}) - " Select a word + " go to the Paste entry in the menu call term_sendkeys(buf, "jj") call VerifyScreenDump(buf, 'Test_popup_command_02', {}) @@ -891,8 +903,20 @@ func Test_popup_command() call VerifyScreenDump(buf, 'Test_popup_command_03', {}) call term_sendkeys(buf, "\<Esc>") + + " Set a timer to change a menu entry while it's displayed. The text should + " not change but the command does. Making the screendump also verifies that + " "changed" shows up, which means the timer triggered + call term_sendkeys(buf, "/X\<CR>:call StartTimer() | popup PopUp\<CR>") + call VerifyScreenDump(buf, 'Test_popup_command_04', {}) + + " Select the Paste entry, executes the changed menu item. + call term_sendkeys(buf, "jj\<CR>") + call VerifyScreenDump(buf, 'Test_popup_command_05', {}) + call StopVimInTerminal(buf) call delete('Xtest') + call delete('XtimerScript') endfunc func Test_popup_complete_backwards() |