vis
a vi-like editor based on Plan 9's structural regular expressions
git clone https://9o.is/git/vis.git
commit 96870b2e3b4bcd874c08ba02b4f855b21d91da1c parent 2545da3e48a572bd1275c71b65ff3d55e65d1aa2 Author: Randy Palamar <palamar@ualberta.ca> Date: Tue, 25 Apr 2023 14:39:02 -0600 fix use after free in cmd_files() When the cmd closes the window the window pointer gets freed along the way. We can't use win->next to update the loop variable if sam_execute() has been called. Instead we can store win->next early and use that variable to continue the loop. fixes #1090 Diffstat:
| M | sam.c | | | 10 | ++++++---- |
1 file changed, 6 insertions(+), 4 deletions(-)
diff --git a/sam.c b/sam.c @@ -1564,14 +1564,16 @@ static bool cmd_print(Vis *vis, Win *win, Command *cmd, const char *argv[], Sele static bool cmd_files(Vis *vis, Win *win, Command *cmd, const char *argv[], Selection *sel, Filerange *range) { bool ret = true; - for (Win *win = vis->windows; win; win = win->next) { - if (win->file->internal) + for (Win *wn, *w = vis->windows; w; w = wn) { + /* w can get freed by sam_execute() so store w->next early */ + wn = w->next; + if (w->file->internal) continue; bool match = !cmd->regex || - (win->file->name && text_regex_match(cmd->regex, win->file->name, 0) == 0); + (w->file->name && text_regex_match(cmd->regex, w->file->name, 0) == 0); if (match ^ (argv[0][0] == 'Y')) { Filerange def = text_range_new(0, 0); - ret &= sam_execute(vis, win, cmd->cmd, NULL, &def); + ret &= sam_execute(vis, w, cmd->cmd, NULL, &def); } } return ret;