From a5b8ea90d2b2fe5a56c166d362ced712f6aa35bb Mon Sep 17 00:00:00 2001 From: emersion Date: Mon, 26 Nov 2018 23:16:40 +0100 Subject: [PATCH] surface: fix destroyed subsurfaces handling wlr_subsurface_from_wlr_surface can return NULL if the wl_surface is still alive and if the wl_subsurface has been destroyed. Make sure we check for NULL. Fixes https://github.com/swaywm/sway/issues/3195 --- include/wlr/types/wlr_compositor.h | 4 ++++ types/wlr_surface.c | 12 +++++++----- 2 files changed, 11 insertions(+), 5 deletions(-) diff --git a/include/wlr/types/wlr_compositor.h b/include/wlr/types/wlr_compositor.h index 1772e54b..36b9e83f 100644 --- a/include/wlr/types/wlr_compositor.h +++ b/include/wlr/types/wlr_compositor.h @@ -43,6 +43,10 @@ struct wlr_compositor *wlr_compositor_create(struct wl_display *display, bool wlr_surface_is_subsurface(struct wlr_surface *surface); +/** + * Get a subsurface from a surface. Can return NULL if the subsurface has been + * destroyed. + */ struct wlr_subsurface *wlr_subsurface_from_wlr_surface( struct wlr_surface *surface); diff --git a/types/wlr_surface.c b/types/wlr_surface.c index b19387c8..27176ef0 100644 --- a/types/wlr_surface.c +++ b/types/wlr_surface.c @@ -376,7 +376,7 @@ static void surface_commit_pending(struct wlr_surface *surface) { } static bool subsurface_is_synchronized(struct wlr_subsurface *subsurface) { - while (1) { + while (subsurface != NULL) { if (subsurface->synchronized) { return true; } @@ -436,15 +436,14 @@ static void surface_commit(struct wl_client *client, struct wl_resource *resource) { struct wlr_surface *surface = wlr_surface_from_resource(resource); - if (wlr_surface_is_subsurface(surface)) { - struct wlr_subsurface *subsurface = - wlr_subsurface_from_wlr_surface(surface); + struct wlr_subsurface *subsurface = wlr_surface_is_subsurface(surface) ? + wlr_subsurface_from_wlr_surface(surface) : NULL; + if (subsurface != NULL) { subsurface_commit(subsurface); } else { surface_commit_pending(surface); } - struct wlr_subsurface *subsurface; wl_list_for_each(subsurface, &surface->subsurfaces, parent_link) { subsurface_parent_commit(subsurface, false); } @@ -904,6 +903,9 @@ struct wlr_surface *wlr_surface_get_root_surface(struct wlr_surface *surface) { while (wlr_surface_is_subsurface(surface)) { struct wlr_subsurface *subsurface = wlr_subsurface_from_wlr_surface(surface); + if (subsurface == NULL) { + break; + } surface = subsurface->parent; } return surface;