aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorzeertzjq <zeertzjq@outlook.com>2022-11-12 09:57:29 +0800
committerGitHub <noreply@github.com>2022-11-12 09:57:29 +0800
commit2425fe2dc5e5985779912319433ddf914a20dd6a (patch)
tree94f06238405f0195241f2264dcb316c7a860acab /src
parenteee956051637a5dff02ba6c6083fbffc87c0c96e (diff)
downloadrneovim-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.c13
-rw-r--r--src/nvim/testdir/test_popup.vim28
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()