summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorKonst Mayer <cdlscpmv@gmail.com>2023-11-18 23:05:01 +0700
committerRafael Marçalo <raroma09@gmail.com>2023-12-05 15:40:16 +0000
commitccc4484add602d36e847b4eace5f475ff24a5f12 (patch)
tree39f973ceca36bb41aec6056442574bbf18907083 /src
parent1a1a232e4a78d5ab3eb55978606db9a6dc4e78b8 (diff)
Prevent use-after-free
Diffstat (limited to 'src')
-rw-r--r--src/autocmd.c19
1 files changed, 16 insertions, 3 deletions
diff --git a/src/autocmd.c b/src/autocmd.c
index f3a1875..8e6af79 100644
--- a/src/autocmd.c
+++ b/src/autocmd.c
@@ -249,9 +249,9 @@ gboolean autocmd_add(Client *c, char *name, gboolean delete)
*/
gboolean autocmd_run(Client *c, AuEvent event, const char *uri, const char *group)
{
- GSList *lg, *lc;
+ GSList *lg, *lc, *lcc;
AuGroup *grp;
- AutoCmd *cmd;
+ AutoCmd *cmd, *new;
guint bits = events[event].bits;
/* if there is no autocmd for this event - skip here */
@@ -266,9 +266,20 @@ gboolean autocmd_run(Client *c, AuEvent event, const char *uri, const char *grou
if (group && strcmp(group, grp->name)) {
continue;
}
- /* test each command in group */
+
+ /* make a deep copy of grp->cmds since it can be modified by ex_run_string() below */
+ lcc = NULL;
for (lc = grp->cmds; lc; lc = lc->next) {
cmd = lc->data;
+ new = new_autocmd(cmd->excmd, cmd->pattern);
+ new->bits = cmd->bits;
+ lcc = g_slist_prepend(lcc, new); // use prepend+reverse instead of append for efficiency
+ }
+ lcc = g_slist_reverse(lcc);
+
+ /* test each command in group */
+ for (lc = lcc; lc; lc = lc->next, free_autocmd(cmd)) {
+ cmd = lc->data;
/* skip if this dos not match the event bits */
if (!(bits & cmd->bits)) {
continue;
@@ -279,6 +290,8 @@ gboolean autocmd_run(Client *c, AuEvent event, const char *uri, const char *grou
continue;
}
}
+
+ g_slist_free(lcc);
}
return true;