mirror of
https://codeberg.org/dnkl/foot.git
synced 2026-06-30 13:14:56 -04:00
notify: fix crash in notify_done() when terminal has been closed before notification
In server mode, if a terminal instance triggered a tracked notification (e.g. a bell notification, or a kitty notification), then the foot server crashed if the terminal instance was closed before the notification. This happened because the notify_done() callback's user supplied argument was the terminal instance, and this pointer was not verified before it was de-referenced. Fix by searching the wayland global's list of terminal instances, and ignore the callback if the wanted terminal instance is gone. Closes #2397
This commit is contained in:
parent
73e6d21000
commit
ebaa878dce
2 changed files with 35 additions and 5 deletions
|
|
@ -114,6 +114,9 @@
|
|||
([#2364][2364]).
|
||||
* Escape quotes in file names being DnD:ed on the command line
|
||||
([#2363][2363]).
|
||||
* Crash in `--server` mode, when a tracked notification is closed
|
||||
after the associated terminal instance has been closed
|
||||
([#2397][2397]).
|
||||
|
||||
[2353]: https://codeberg.org/dnkl/foot/issues/2353
|
||||
[2352]: https://codeberg.org/dnkl/foot/issues/2352
|
||||
|
|
@ -122,6 +125,7 @@
|
|||
[2360]: https://codeberg.org/dnkl/foot/issues/2360
|
||||
[2370]: https://codeberg.org/dnkl/foot/issues/2370
|
||||
[2364]: https://codeberg.org/dnkl/foot/issues/2364
|
||||
[2397]: https://codeberg.org/dnkl/foot/issues/2397
|
||||
|
||||
|
||||
### Security
|
||||
|
|
|
|||
36
notify.c
36
notify.c
|
|
@ -233,10 +233,31 @@ fdm_notify_stdout(struct fdm *fdm, int fd, int events, void *data)
|
|||
return true;
|
||||
}
|
||||
|
||||
struct done_context {
|
||||
struct wayland *wayl;
|
||||
struct terminal *term;
|
||||
};
|
||||
|
||||
static void
|
||||
notif_done(struct reaper *reaper, pid_t pid, int status, void *data)
|
||||
{
|
||||
struct terminal *term = data;
|
||||
struct done_context *ctx = data;
|
||||
const struct wayland *wayl = ctx->wayl;
|
||||
const struct terminal *wanted_term = ctx->term;
|
||||
free(ctx);
|
||||
|
||||
struct terminal *term = NULL;
|
||||
tll_foreach(wayl->terms, it) {
|
||||
if (it->item == wanted_term) {
|
||||
term = it->item;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (term == NULL) {
|
||||
LOG_WARN("notification closed, but the associated terminal instance is already gone");
|
||||
return;
|
||||
}
|
||||
|
||||
tll_foreach(term->active_notifications, it) {
|
||||
struct notification *notif = &it->item;
|
||||
|
|
@ -567,11 +588,18 @@ notify_notify(struct terminal *term, struct notification *notif)
|
|||
&fdm_notify_stdout, (void *)term);
|
||||
}
|
||||
|
||||
struct done_context *ctx = NULL;
|
||||
if (track_notification) {
|
||||
ctx = xmalloc(sizeof(*ctx));
|
||||
ctx->wayl = term->wl;
|
||||
ctx->term = term;
|
||||
}
|
||||
|
||||
/* Redirect stdin to /dev/null, but ignore failure to open */
|
||||
int devnull = open("/dev/null", O_RDONLY);
|
||||
pid_t pid = spawn(
|
||||
term->reaper, NULL, argv, devnull, stdout_fds[1], -1,
|
||||
track_notification ? ¬if_done : NULL, (void *)term, NULL);
|
||||
track_notification ? ¬if_done : NULL, ctx, NULL);
|
||||
|
||||
if (stdout_fds[1] >= 0) {
|
||||
/* Close write-end of stdout pipe */
|
||||
|
|
@ -649,9 +677,7 @@ notify_close(struct terminal *term, const char *id)
|
|||
}
|
||||
|
||||
int devnull = open("/dev/null", O_RDONLY);
|
||||
spawn(
|
||||
term->reaper, NULL, argv, devnull, -1, -1,
|
||||
NULL, (void *)term, NULL);
|
||||
spawn(term->reaper, NULL, argv, devnull, -1, -1, NULL, NULL, NULL);
|
||||
|
||||
if (devnull >= 0)
|
||||
close(devnull);
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue