From 55298377fa041ab86f54d557c3fd4eba86b83fcd Mon Sep 17 00:00:00 2001
From: Marko Lindqvist <cazfi74@gmail.com>
Date: Sat, 7 Nov 2026 19:36:11 +0200
Subject: [PATCH 34/34] gtk4 gui_dialog_destroy(): Fix use-after-free

Destroying the window or notebook page can lead to
the destruction of the entire dialog structure.
Make sure we don't access any members of it after that.
This was leading to a crash on client launch on MacOS.

Reported by Jan Szurek

See RM #2447

Signed-off-by: Marko Lindqvist <cazfi74@gmail.com>
---
 client/gui-gtk-4.0/gui_stuff.c | 24 +++++++++++++++---------
 1 file changed, 15 insertions(+), 9 deletions(-)

diff --git a/client/gui-gtk-4.0/gui_stuff.c b/client/gui-gtk-4.0/gui_stuff.c
index 5dd68c8b76..8e0d9972fa 100644
--- a/client/gui-gtk-4.0/gui_stuff.c
+++ b/client/gui-gtk-4.0/gui_stuff.c
@@ -873,31 +873,37 @@ void gui_dialog_set_title(struct gui_dialog *dlg, const char *title)
 **************************************************************************/
 void gui_dialog_destroy(struct gui_dialog *dlg)
 {
+  if (dlg->source != NULL) {
+    *(dlg->source) = NULL;
+  }
+
   switch (dlg->type) {
   case GUI_DIALOG_WINDOW:
     if (dlg->v.window != NULL) {
+      /* Destruction of the window can lead to the destruction of
+       * the entire dialog structure, via destrucion handler of
+       * dlg->v.grid. Be sure not to reference it after this. */
       gtk_window_destroy(GTK_WINDOW(dlg->v.window));
-      dlg->v.window = NULL;
     }
     break;
   case GUI_DIALOG_TAB:
     {
       gint n;
+      GtkNotebook *notebook = GTK_NOTEBOOK(dlg->v.tab.notebook);
+      gulong handler = dlg->v.tab.handler_id;
 
-      n = gtk_notebook_page_num(GTK_NOTEBOOK(dlg->v.tab.notebook), dlg->grid);
+      n = gtk_notebook_page_num(notebook, dlg->grid);
 
       fc_assert(n >= 0);
 
-      gtk_notebook_remove_page(GTK_NOTEBOOK(dlg->v.tab.notebook), n);
-      g_signal_handler_disconnect(GTK_NOTEBOOK(dlg->v.tab.notebook),
-                                  dlg->v.tab.handler_id);
+      /* Destruction of the notebook page can lead to the destruction of
+       * the entire dialog structure, via destrucion handler of
+       * dlg->v.grid. Be sure not to reference it after this. */
+      gtk_notebook_remove_page(notebook, n);
+      g_signal_handler_disconnect(notebook, handler);
     }
     break;
   }
-
-  if (dlg->source != NULL) {
-    *(dlg->source) = NULL;
-  }
 }
 
 /**********************************************************************//**
-- 
2.53.0

