mirror of
https://github.com/vim/vim.git
synced 2025-10-01 04:54:07 -04:00
patch 8.2.2207: illegal memory access if popup menu items are changed
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)
This commit is contained in:
@@ -1458,10 +1458,21 @@ pum_show_popupmenu(vimmenu_T *menu)
|
|||||||
return;
|
return;
|
||||||
|
|
||||||
FOR_ALL_CHILD_MENUS(menu, mp)
|
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))
|
if (menu_is_separator(mp->dname))
|
||||||
array[idx++].pum_text = (char_u *)"";
|
s = (char_u *)"";
|
||||||
else if (mp->modes & mp->enabled & mode)
|
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_array = array;
|
||||||
pum_compute_size();
|
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);
|
vim_free(array);
|
||||||
pum_undisplay();
|
pum_undisplay();
|
||||||
# ifdef FEAT_BEVAL_TERM
|
# ifdef FEAT_BEVAL_TERM
|
||||||
|
20
src/testdir/dumps/Test_popup_command_04.dump
Normal file
20
src/testdir/dumps/Test_popup_command_04.dump
Normal file
@@ -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
|
20
src/testdir/dumps/Test_popup_command_05.dump
Normal file
20
src/testdir/dumps/Test_popup_command_05.dump
Normal file
@@ -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|
|
@@ -859,18 +859,30 @@ func Test_popup_command()
|
|||||||
call assert_fails('popup Foo', 'E337:')
|
call assert_fails('popup Foo', 'E337:')
|
||||||
unmenu Test.Foo
|
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
|
let lines =<< trim END
|
||||||
one two three four five
|
one two three four five
|
||||||
and one two Xthree four five
|
and one two Xthree four five
|
||||||
one more two three four five
|
one more two three four five
|
||||||
END
|
END
|
||||||
call writefile(lines, 'Xtest')
|
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, ":source $VIMRUNTIME/menu.vim\<CR>")
|
||||||
call term_sendkeys(buf, "/X\<CR>:popup PopUp\<CR>")
|
call term_sendkeys(buf, "/X\<CR>:popup PopUp\<CR>")
|
||||||
call VerifyScreenDump(buf, 'Test_popup_command_01', {})
|
call VerifyScreenDump(buf, 'Test_popup_command_01', {})
|
||||||
|
|
||||||
" Select a word
|
" go to the Paste entry in the menu
|
||||||
call term_sendkeys(buf, "jj")
|
call term_sendkeys(buf, "jj")
|
||||||
call VerifyScreenDump(buf, 'Test_popup_command_02', {})
|
call VerifyScreenDump(buf, 'Test_popup_command_02', {})
|
||||||
|
|
||||||
@@ -879,8 +891,20 @@ func Test_popup_command()
|
|||||||
call VerifyScreenDump(buf, 'Test_popup_command_03', {})
|
call VerifyScreenDump(buf, 'Test_popup_command_03', {})
|
||||||
|
|
||||||
call term_sendkeys(buf, "\<Esc>")
|
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 StopVimInTerminal(buf)
|
||||||
call delete('Xtest')
|
call delete('Xtest')
|
||||||
|
call delete('XtimerScript')
|
||||||
endfunc
|
endfunc
|
||||||
|
|
||||||
func Test_popup_complete_backwards()
|
func Test_popup_complete_backwards()
|
||||||
|
@@ -750,6 +750,8 @@ static char *(features[]) =
|
|||||||
|
|
||||||
static int included_patches[] =
|
static int included_patches[] =
|
||||||
{ /* Add new patch number below this line */
|
{ /* Add new patch number below this line */
|
||||||
|
/**/
|
||||||
|
2207,
|
||||||
/**/
|
/**/
|
||||||
2206,
|
2206,
|
||||||
/**/
|
/**/
|
||||||
|
Reference in New Issue
Block a user