From 67b4ecd8430dd521435ea5fb93cc932e43a62a81 Mon Sep 17 00:00:00 2001 From: project-repo Date: Fri, 18 Sep 2020 07:37:27 +0200 Subject: [PATCH] Fix use-after-free when destroying popups --- view.c | 29 +++++++++++++++++++++-------- view.h | 4 +++- xdg_shell.c | 4 +--- 3 files changed, 25 insertions(+), 12 deletions(-) diff --git a/view.c b/view.c index a7817cf..db5a916 100644 --- a/view.c +++ b/view.c @@ -43,17 +43,17 @@ view_get_prev_view(struct cg_view *view) { } void -view_damage_child(struct cg_view_child *child, int x, int y, bool whole) { - output_damage_surface(child->view->workspace->output, child->wlr_surface, x, - y, whole); +view_damage_child(struct cg_view_child *child, bool whole) { + int x, y; + child->get_coords(child, &x, &y); + output_damage_surface(child->view->workspace->output, child->wlr_surface, x+child->view->ox, + y+child->view->oy, whole); } static void view_child_handle_commit(struct wl_listener *listener, void *_data) { struct cg_view_child *child = wl_container_of(listener, child, commit); - int x, y; - child->get_coords(child, &x, &y); - view_damage_child(child, x + child->view->ox, y + child->view->oy, false); + view_damage_child(child, false); } static void @@ -74,11 +74,20 @@ view_child_finish(struct cg_view_child *child) { return; } - if(child->view != NULL && child->view->wlr_surface != NULL) { - view_damage_whole(child->view); + if(child->view != NULL) { + view_damage_child(child, true); + } + + struct cg_view_child *subchild, *tmpchild; + wl_list_for_each_safe(subchild,tmpchild, &child->children,parent_link) { + subchild->parent=NULL; + wl_list_remove(&subchild->parent_link); } wl_list_remove(&child->link); + if(child->parent != NULL) { + wl_list_remove(&child->parent_link); + } wl_list_remove(&child->commit.link); wl_list_remove(&child->new_subsurface.link); } @@ -88,7 +97,11 @@ view_child_init(struct cg_view_child *child, struct cg_view_child *parent, struct cg_view *view, struct wlr_surface *wlr_surface) { child->view = view; child->parent = parent; + if(parent != NULL) { + wl_list_insert(&parent->children,&child->parent_link); + } child->wlr_surface = wlr_surface; + wl_list_init(&child->children); child->commit.notify = view_child_handle_commit; wl_signal_add(&wlr_surface->events.commit, &child->commit); diff --git a/view.h b/view.h index 7474198..251c00f 100644 --- a/view.h +++ b/view.h @@ -53,8 +53,10 @@ struct cg_view_impl { struct cg_view_child { struct cg_view *view; struct cg_view_child *parent; + struct wl_list children; struct wlr_surface *wlr_surface; struct wl_list link; + struct wl_list parent_link; struct wl_listener commit; struct wl_listener new_subsurface; @@ -83,7 +85,7 @@ view_damage_part(struct cg_view *view); void view_damage_whole(struct cg_view *view); void -view_damage_child(struct cg_view_child *view, int x, int y, bool whole); +view_damage_child(struct cg_view_child *view, bool whole); void view_activate(struct cg_view *view, bool activate); void diff --git a/xdg_shell.c b/xdg_shell.c index 9c076f2..6a65e01 100644 --- a/xdg_shell.c +++ b/xdg_shell.c @@ -58,9 +58,7 @@ xdg_popup_destroy(struct cg_view_child *child) { return; } - int x, y; - child->get_coords(child, &x, &y); - view_damage_child(child, x + child->view->ox, y + child->view->oy, true); + view_damage_child(child, true); struct cg_xdg_popup *popup = (struct cg_xdg_popup *)child; wl_list_remove(&popup->destroy.link); wl_list_remove(&popup->map.link);