diff options
author | Bram Moolenaar <Bram@vim.org> | 2020-12-24 18:39:02 +0100 |
---|---|---|
committer | Bram Moolenaar <Bram@vim.org> | 2020-12-24 18:39:02 +0100 |
commit | 38455a921395a56690790c8c1d28c1c43ca04c8a (patch) | |
tree | d762d33f56f9375c80a61b1072382138e287413f | |
parent | 0261a1aeeb4ccec4ef75cc8e0685c78f5622dbf5 (diff) | |
download | vim-git-38455a921395a56690790c8c1d28c1c43ca04c8a.tar.gz |
patch 8.2.2207: illegal memory access if popup menu items are changedv8.2.2207
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 #7537)
-rw-r--r-- | src/popupmenu.c | 17 | ||||
-rw-r--r-- | src/testdir/dumps/Test_popup_command_04.dump | 20 | ||||
-rw-r--r-- | src/testdir/dumps/Test_popup_command_05.dump | 20 | ||||
-rw-r--r-- | src/testdir/test_popup.vim | 28 | ||||
-rw-r--r-- | src/version.c | 2 |
5 files changed, 83 insertions, 4 deletions
diff --git a/src/popupmenu.c b/src/popupmenu.c index c8d305cbc..1f9840804 100644 --- a/src/popupmenu.c +++ b/src/popupmenu.c @@ -1458,10 +1458,21 @@ pum_show_popupmenu(vimmenu_T *menu) return; FOR_ALL_CHILD_MENUS(menu, mp) + { + char_u *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 = (char_u *)""; else if (mp->modes & mp->enabled & mode) - array[idx++].pum_text = mp->dname; + s = mp->dname; + if (s != NULL) + { + s = vim_strsave(s); + if (s != NULL) + array[idx++].pum_text = s; + } + } pum_array = array; pum_compute_size(); @@ -1542,6 +1553,8 @@ pum_show_popupmenu(vimmenu_T *menu) } } + for (idx = 0; idx < pum_size; ++idx) + vim_free(array[idx].pum_text); vim_free(array); pum_undisplay(); # ifdef FEAT_BEVAL_TERM diff --git a/src/testdir/dumps/Test_popup_command_04.dump b/src/testdir/dumps/Test_popup_command_04.dump new file mode 100644 index 000000000..c14576cd8 --- /dev/null +++ b/src/testdir/dumps/Test_popup_command_04.dump @@ -0,0 +1,20 @@ +|o+0&#ffffff0|n|e| |t|w|o| |t|h|r|e@1| |f|o|u|r| |f|i|v|e| @51 +|a|n|d| |o|n|e| |t|w|o| |X|t|h|r|e@1| |f|o|u|r| |f|i|v|e| @46 +|o|n|e| |m|o|r|e| |t|w| +0#0000001#ffd7ff255|U|n|d|o| @12| +0#0000000#ffffff0@45 +|~+0#4040ff13&| @9| +0#0000001#ffd7ff255@17| +0#4040ff13#ffffff0@45 +|~| @9| +0#0000001#ffd7ff255|P|a|s|t|e| @11| +0#4040ff13#ffffff0@45 +|~| @9| +0#0000001#ffd7ff255@17| +0#4040ff13#ffffff0@45 +|~| @9| +0#0000001#ffd7ff255|S|e|l|e|c|t| |W|o|r|d| @5| +0#4040ff13#ffffff0@45 +|~| @9| +0#0000001#ffd7ff255|S|e|l|e|c|t| |S|e|n|t|e|n|c|e| @1| +0#4040ff13#ffffff0@45 +|~| @9| +0#0000001#ffd7ff255|S|e|l|e|c|t| |P|a|r|a|g|r|a|p|h| | +0#4040ff13#ffffff0@45 +|~| @9| +0#0000001#ffd7ff255|S|e|l|e|c|t| |L|i|n|e| @5| +0#4040ff13#ffffff0@45 +|~| @9| +0#0000001#ffd7ff255|S|e|l|e|c|t| |B|l|o|c|k| @4| +0#4040ff13#ffffff0@45 +|~| @9| +0#0000001#ffd7ff255|S|e|l|e|c|t| |A|l@1| @6| +0#4040ff13#ffffff0@45 +|~| @73 +|~| @73 +|~| @73 +|~| @73 +|~| @73 +|~| @73 +|~| @73 +|c+0#0000000&|h|a|n|g|e|d> @67 diff --git a/src/testdir/dumps/Test_popup_command_05.dump b/src/testdir/dumps/Test_popup_command_05.dump new file mode 100644 index 000000000..de1c95e86 --- /dev/null +++ b/src/testdir/dumps/Test_popup_command_05.dump @@ -0,0 +1,20 @@ +|o+0&#ffffff0|n|e| |t|w|o| |t|h|r|e@1| |f|o|u|r| |f|i|v|e| @51 +|a|n|d| |o|n|e| |t|w|o| >X|t|h|r|e@1| |f|o|u|r| |f|i|v|e| @46 +|o|n|e| |m|o|r|e| |t|w|o| |t|h|r|e@1| |f|o|u|r| |f|i|v|e| @46 +|~+0#4040ff13&| @73 +|~| @73 +|~| @73 +|~| @73 +|~| @73 +|~| @73 +|~| @73 +|~| @73 +|~| @73 +|~| @73 +|~| @73 +|~| @73 +|~| @73 +|~| @73 +|~| @73 +|~| @73 +|p+0#0000000&|a|s|t|e|d| @50|2|,|1|3| @9|A|l@1| diff --git a/src/testdir/test_popup.vim b/src/testdir/test_popup.vim index 28481b3a2..9175ff1f2 100644 --- a/src/testdir/test_popup.vim +++ b/src/testdir/test_popup.vim @@ -859,18 +859,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', {}) @@ -879,8 +891,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() diff --git a/src/version.c b/src/version.c index adba2cd4e..a5394f931 100644 --- a/src/version.c +++ b/src/version.c @@ -751,6 +751,8 @@ static char *(features[]) = static int included_patches[] = { /* Add new patch number below this line */ /**/ + 2207, +/**/ 2206, /**/ 2205, |