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)