patch 9.0.0877: using freed memory with :comclear while listing commands

Problem:    Using freed memory with :comclear while listing commands.
Solution:   Bail out when the command list has changed. (closes #11440)
diff --git a/src/usercmd.c b/src/usercmd.c
index 9f16680..d878332 100644
--- a/src/usercmd.c
+++ b/src/usercmd.c
@@ -31,6 +31,9 @@
 // List of all user commands.
 static garray_T ucmds = {0, 0, sizeof(ucmd_T), 4, NULL};
 
+// When non-zero it is not allowed to add or remove user commands
+static int ucmd_locked = 0;
+
 #define USER_CMD(i) (&((ucmd_T *)(ucmds.ga_data))[i])
 #define USER_CMD_GA(gap, i) (&((ucmd_T *)((gap)->ga_data))[i])
 
@@ -499,6 +502,9 @@
     long	a;
     garray_T	*gap;
 
+    // don't allow for adding or removing user commands here
+    ++ucmd_locked;
+
     // In cmdwin, the alternative buffer should be used.
     gap = &prevwin_curwin()->w_buffer->b_ucmds;
     for (;;)
@@ -656,6 +662,8 @@
 
     if (!found)
 	msg(_("No user-defined commands found"));
+
+    --ucmd_locked;
 }
 
     char *
@@ -1223,6 +1231,21 @@
 }
 
 /*
+ * If ucmd_locked is set give an error and return TRUE.
+ * Otherwise return FALSE.
+ */
+    static int
+is_ucmd_locked(void)
+{
+    if (ucmd_locked > 0)
+    {
+	emsg(_(e_cannot_change_user_commands_while_listing));
+	return TRUE;
+    }
+    return FALSE;
+}
+
+/*
  * Clear all user commands for "gap".
  */
     void
@@ -1231,6 +1254,9 @@
     int		i;
     ucmd_T	*cmd;
 
+    if (is_ucmd_locked())
+	return;
+
     for (i = 0; i < gap->ga_len; ++i)
     {
 	cmd = USER_CMD_GA(gap, i);
@@ -1285,6 +1311,9 @@
 	return;
     }
 
+    if (is_ucmd_locked())
+	return;
+
     vim_free(cmd->uc_name);
     vim_free(cmd->uc_rep);
 # if defined(FEAT_EVAL)