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:
Msam.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;