[gtk/gtk-3-24: 1/2] gdkquartz: fix crash on uninitialized attribute




commit 71e2821578c32e5680739415ce7a38bb57ac0ceb
Author: Lukas Oberhuber <lukaso gmail com>
Date:   Thu Dec 16 13:00:02 2021 +0000

    gdkquartz: fix crash on uninitialized attribute
    
    `gdk_quartz_display_get_monitor_at_window` crashes when it tries to access the NSWindow on
    an offscreen window. The attribute `toplevel` of `impl` is uninitialized and
    causes a segfault.
    
    This partially fixes: https://gitlab.gnome.org/GNOME/gimp/-/issues/7608

 gdk/quartz/gdkdisplay-quartz.c | 26 +++++++++++++++++++++++---
 gdk/quartz/gdkwindow-quartz.c  |  1 +
 2 files changed, 24 insertions(+), 3 deletions(-)
---
diff --git a/gdk/quartz/gdkdisplay-quartz.c b/gdk/quartz/gdkdisplay-quartz.c
index 6186b32925..0587ca8f2f 100644
--- a/gdk/quartz/gdkdisplay-quartz.c
+++ b/gdk/quartz/gdkdisplay-quartz.c
@@ -33,6 +33,7 @@
 #include "gdkmonitor-quartz.h"
 #include "gdkglcontext-quartz.h"
 #include "gdkinternal-quartz.h"
+#include "gdkwindow.h"
 
 /* Note about coordinates: There are three coordinate systems at play:
  *
@@ -453,10 +454,29 @@ static GdkMonitor *
 gdk_quartz_display_get_monitor_at_window (GdkDisplay *display,
                                           GdkWindow *window)
 {
-  GdkWindowImplQuartz *impl = GDK_WINDOW_IMPL_QUARTZ (window->impl);
-  NSWindow *nswindow = impl->toplevel;
-  NSScreen *screen = [nswindow screen];
+  GdkWindowImplQuartz *impl = NULL;
+  NSWindow *nswindow = NULL;
+  NSScreen *screen = NULL;
   GdkMonitor *monitor = NULL;
+  GdkWindow *onscreen_window = window;
+
+  /*
+   * This stops crashes when there is no NSWindow available on
+   * an offscreen window which occurs for children of children
+   * of an onscreen window (children of an onscreen window do
+   * have NSWindow set)
+   * https://gitlab.gnome.org/GNOME/gimp/-/issues/7608
+   */
+  while (onscreen_window && onscreen_window->window_type == GDK_WINDOW_OFFSCREEN)
+    onscreen_window = onscreen_window->parent;
+
+  if (!onscreen_window)
+    return NULL;
+
+  impl = GDK_WINDOW_IMPL_QUARTZ (onscreen_window->impl);
+  nswindow = impl->toplevel;
+  screen = [nswindow screen];
+
   if (screen)
   {
     GdkQuartzDisplay *quartz_display = GDK_QUARTZ_DISPLAY (display);
diff --git a/gdk/quartz/gdkwindow-quartz.c b/gdk/quartz/gdkwindow-quartz.c
index a5c5c31945..30e62a7574 100644
--- a/gdk/quartz/gdkwindow-quartz.c
+++ b/gdk/quartz/gdkwindow-quartz.c
@@ -879,6 +879,7 @@ _gdk_quartz_display_create_window_impl (GdkDisplay    *display,
                                  NULL));
 
   impl->view = NULL;
+  impl->toplevel = NULL;
 
   if (attributes_mask & GDK_WA_TYPE_HINT)
     {


[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]