0
0
mirror of https://github.com/vim/vim.git synced 2025-09-28 04:24:06 -04:00

patch 9.0.0874: using freed memory when executing unmenu at more prompt

Problem:    Using freed memory when executing unmenu at the more prompt.
Solution:   Do not clear menus while listing them. (closes #11439)
This commit is contained in:
Bram Moolenaar
2022-11-13 21:10:02 +00:00
parent bf533e4e88
commit 920d311480
4 changed files with 63 additions and 3 deletions

View File

@@ -3335,3 +3335,7 @@ EXTERN char e_cannot_resize_window_in_another_tab_page[]
#endif #endif
EXTERN char e_cannot_change_mappings_while_listing[] EXTERN char e_cannot_change_mappings_while_listing[]
INIT(= N_("E1309: Cannot change mappings while listing")); INIT(= N_("E1309: Cannot change mappings while listing"));
#if defined(FEAT_MENU)
EXTERN char e_cannot_change_menus_while_listing[]
INIT(= N_("E1310: Cannot change menus while listing"));
#endif

View File

@@ -46,6 +46,10 @@ static int s_tearoffs = FALSE;
static int menu_is_hidden(char_u *name); static int menu_is_hidden(char_u *name);
static int menu_is_tearoff(char_u *name); static int menu_is_tearoff(char_u *name);
// When non-zero no menu must be added or cleared. Prevents the list of menus
// changing while listing them.
static int menus_locked = 0;
#if defined(FEAT_MULTI_LANG) || defined(FEAT_TOOLBAR) #if defined(FEAT_MULTI_LANG) || defined(FEAT_TOOLBAR)
static char_u *menu_skip_part(char_u *p); static char_u *menu_skip_part(char_u *p);
#endif #endif
@@ -98,6 +102,21 @@ get_root_menu(char_u *name)
return &root_menu; return &root_menu;
} }
/*
* If "menus_locked" is set then give an error and return TRUE.
* Otherwise return FALSE.
*/
static int
is_menus_locked(void)
{
if (menus_locked > 0)
{
emsg(_(e_cannot_change_menus_while_listing));
return TRUE;
}
return FALSE;
}
/* /*
* Do the :menu command and relatives. * Do the :menu command and relatives.
*/ */
@@ -329,6 +348,9 @@ ex_menu(
} }
else if (unmenu) else if (unmenu)
{ {
if (is_menus_locked())
goto theend;
/* /*
* Delete menu(s). * Delete menu(s).
*/ */
@@ -357,6 +379,9 @@ ex_menu(
} }
else else
{ {
if (is_menus_locked())
goto theend;
/* /*
* Add menu(s). * Add menu(s).
* Replace special key codes. * Replace special key codes.
@@ -1147,11 +1172,14 @@ show_menus(char_u *path_name, int modes)
} }
vim_free(path_name); vim_free(path_name);
// Now we have found the matching menu, and we list the mappings // make sure the list of menus doesn't change while listing them
// Highlight title ++menus_locked;
msg_puts_title(_("\n--- Menus ---"));
// list the matching menu mappings
msg_puts_title(_("\n--- Menus ---"));
show_menus_recursive(parent, modes, 0); show_menus_recursive(parent, modes, 0);
--menus_locked;
return OK; return OK;
} }

View File

@@ -3,6 +3,8 @@
source check.vim source check.vim
CheckFeature menu CheckFeature menu
source screendump.vim
func Test_load_menu() func Test_load_menu()
try try
source $VIMRUNTIME/menu.vim source $VIMRUNTIME/menu.vim
@@ -568,4 +570,28 @@ func Test_only_modifier()
tunmenu a.b tunmenu a.b
endfunc endfunc
func Test_mapclear_while_listing()
CheckRunVimInTerminal
let lines =<< trim END
set nocompatible
unmenu *
for i in range(1, 999)
exe 'menu ' .. 'foo.' .. i .. ' bar'
endfor
au CmdlineLeave : call timer_start(0, {-> execute('unmenu *')})
END
call writefile(lines, 'Xmenuclear', 'D')
let buf = RunVimInTerminal('-S Xmenuclear', {'rows': 10})
" this was using freed memory
call term_sendkeys(buf, ":menu\<CR>")
call TermWait(buf, 50)
call term_sendkeys(buf, "G")
call TermWait(buf, 50)
call term_sendkeys(buf, "\<CR>")
call StopVimInTerminal(buf)
endfunc
" vim: shiftwidth=2 sts=2 expandtab " vim: shiftwidth=2 sts=2 expandtab

View File

@@ -695,6 +695,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 */
/**/
874,
/**/ /**/
873, 873,
/**/ /**/