From 6fd533ce138bbb2d026da8175353feb493b12b47 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Daniel=20Ekl=C3=B6f?= Date: Thu, 29 Feb 2024 07:49:08 +0100 Subject: [PATCH] render: don't try to set a NULL xcursor image render_xcursor_update() is called when we've loaded a new xcursor image, and needs to display it. The reason it's not pushed to the compositor immediately is to ensure we don't flood the Wayland socket with xcursor updates. Normally, it's only called when we *succeed* to load a new xcursor image. I.e. if we try to load a non-existing xcursor image, we never schedule an update. However, we _can_ still end up in render_xcursor_update() without a valid xcursor image. For example, we have loaded a valid xcursor image, and scheduled an update. But before the update runs, the user moves the cursor, and we try to load a new xcursor image. If it fails, we crash when the previously scheduled update finally runs. Closes #1624 --- CHANGELOG.md | 2 ++ render.c | 19 +++++++++++++++++-- 2 files changed, 19 insertions(+), 2 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 6ca6d88a..0b06bf41 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -122,12 +122,14 @@ affect emojis. * Pressing a modifier key while the kitty keyboard protocol is enabled no longer resets the viewport, or clears the selection. +* Crash when failing to load an xcursor image ([#1624][1624]). [1531]: https://codeberg.org/dnkl/foot/issues/1531 [1573]: https://codeberg.org/dnkl/foot/issues/1573 [1568]: https://codeberg.org/dnkl/foot/issues/1568 [1552]: https://codeberg.org/dnkl/foot/issues/1552 [1610]: https://codeberg.org/dnkl/foot/issues/1610 +[1624]: https://codeberg.org/dnkl/foot/issues/1624 ### Security diff --git a/render.c b/render.c index 4f0d2348..3ce8a226 100644 --- a/render.c +++ b/render.c @@ -4363,8 +4363,6 @@ render_xcursor_update(struct seat *seat) return; } - xassert(seat->pointer.cursor != NULL); - const enum cursor_shape shape = seat->pointer.shape; const char *const xcursor = seat->pointer.last_custom_xcursor; @@ -4398,6 +4396,23 @@ render_xcursor_update(struct seat *seat) LOG_DBG("setting %scursor shape using a client-side cursor surface", seat->pointer.shape == CURSOR_SHAPE_CUSTOM ? "custom " : ""); + if (seat->pointer.cursor == NULL) { + /* + * Normally, we never get here with a NULL-cursor, because we + * only schedule a cursor update when we succeed to load the + * cursor image. + * + * However, it is possible that we did succeed to load an + * image, and scheduled an update. But, *before* the scheduled + * update triggers, the user mvoes the pointer, and we try to + * load a new cursor image. This time failing. + * + * In this case, we have a NULL cursor, but the scheduled + * update is still scheduled. + */ + return; + } + const float scale = seat->pointer.scale; struct wl_cursor_image *image = seat->pointer.cursor->images[0]; struct wl_buffer *buf = wl_cursor_image_get_buffer(image);