diff src/menu.c @ 31079:082f526cfb96 v9.0.0874

patch 9.0.0874: using freed memory when executing unmenu at more prompt Commit: https://github.com/vim/vim/commit/920d311480114274e4d73156edf4b49ba0b712dd Author: Bram Moolenaar <Bram@vim.org> Date: Sun Nov 13 21:10:02 2022 +0000 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 https://github.com/vim/vim/issues/11439)
author Bram Moolenaar <Bram@vim.org>
date Sun, 13 Nov 2022 22:15:02 +0100
parents 91ecee475811
children 238ca27dbfd2
line wrap: on
line diff
--- a/src/menu.c
+++ b/src/menu.c
@@ -46,6 +46,10 @@ static int s_tearoffs = FALSE;
 static int menu_is_hidden(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)
 static char_u *menu_skip_part(char_u *p);
 #endif
@@ -99,6 +103,21 @@ get_root_menu(char_u *name)
 }
 
 /*
+ * 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.
  */
     void
@@ -329,6 +348,9 @@ ex_menu(
     }
     else if (unmenu)
     {
+	if (is_menus_locked())
+	    goto theend;
+
 	/*
 	 * Delete menu(s).
 	 */
@@ -357,6 +379,9 @@ ex_menu(
     }
     else
     {
+	if (is_menus_locked())
+	    goto theend;
+
 	/*
 	 * Add menu(s).
 	 * Replace special key codes.
@@ -1147,11 +1172,14 @@ show_menus(char_u *path_name, int modes)
     }
     vim_free(path_name);
 
-    // Now we have found the matching menu, and we list the mappings
-						    // Highlight title
+    // make sure the list of menus doesn't change while listing them
+    ++menus_locked;
+
+    // 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;
 }