]> git.mdlowis.com Git - proto/labwc.git/commitdiff
menu: fix UAF in client-list-combined-menu after window destruction
authorJohan Malm <jgm323@gmail.com>
Wed, 23 Oct 2024 19:47:50 +0000 (20:47 +0100)
committerJohan Malm <johanmalm@users.noreply.github.com>
Thu, 24 Oct 2024 19:52:17 +0000 (20:52 +0100)
Update client-list-combined-menu when a window is destroyed to avoid
SEGFAULT when selecting an that window entry in it.

include/menu/menu.h
src/menu/menu.c
src/view.c

index f55bc365ba93285f3c673af550fa6a5c05446dbe..4dd98796a90b09ce771b658f43ec02ec51c2ea57 100644 (file)
@@ -85,6 +85,7 @@ bool menu_call_selected_actions(struct server *server);
 
 void menu_init(struct server *server);
 void menu_finish(struct server *server);
+void menu_on_view_destroy(struct view *view);
 
 /**
  * menu_get_by_id - get menu by id
index 882b1eeed750657af08eb531083458b7defaeada..6092ce9e61981e56c151ec3fab3a4c28128b4c29 100644 (file)
@@ -1190,6 +1190,36 @@ menu_finish(struct server *server)
        current_menu = NULL;
 }
 
+void
+menu_on_view_destroy(struct view *view)
+{
+       struct server *server = view->server;
+
+       /* If the view being destroy has an open window menu, then close it */
+       if (server->menu_current
+                       && server->menu_current->triggered_by_view == view) {
+               menu_close_root(server);
+       }
+
+       /*
+        * TODO: Instead of just setting client_list_view to NULL and deleting
+        * the actions (as below), consider destroying the item and somehow
+        * updating the menu and its selection state.
+        */
+
+       /* Also nullify the destroyed view in client-list-combined-menu */
+       struct menu *menu = menu_get_by_id(server, "client-list-combined-menu");
+       if (menu) {
+               struct menuitem *item;
+               wl_list_for_each(item, &menu->menuitems, link) {
+                       if (item->client_list_view == view) {
+                               item->client_list_view = NULL;
+                               action_list_free(&item->actions);
+                       }
+               }
+       }
+}
+
 /* Sets selection (or clears selection if passing NULL) */
 static void
 menu_set_selection(struct menu *menu, struct menuitem *item)
index bcb86ea0bdb442c4ed828825efc286ccecee816a..bdf386bab4aaf8448a219eb463773387e7ac958e 100644 (file)
@@ -2453,11 +2453,7 @@ view_destroy(struct view *view)
                }
        }
 
-       /* If we spawned a window menu, close it */
-       if (server->menu_current
-                       && server->menu_current->triggered_by_view == view) {
-               menu_close_root(server);
-       }
+       menu_on_view_destroy(view);
 
        /*
         * Destroy the view's scene tree. View methods assume this is non-NULL,