[plasma/spectacle/Plasma/6.7] src/Platforms: Fix crash when window is destroyed during window-under-pointer detection

Noah Davis <[email protected]> Tue, 4 Aug 2026 16:24:49 +0000 (UTC)
Newsgroups gmane.comp.kde.cvs
Message-ID <[email protected]>
Git commit 5f37568f34ead2a5abe9cf13fc0d36a69c66b9e2 by Noah Davis.
Committed on 04/08/2026 at 15:04.
Pushed by ndavis into branch 'Plasma/6.7'.

Fix crash when window is destroyed during window-under-pointer detection

xcb_get_property_reply(), xcb_query_tree_reply(), xcb_intern_atom_reply(), and xcb_query_pointer_reply() can all return null if the target window is destroyed between the request and the reply, or on connection error. This function dereferenced all of them unconditionally, causing a crash when a window (e.g. a short-lived popup or tooltip) closes mid-query.

Add null checks, falling back to the root window or skipping the affected branch of the tree walk as appropriate.


(cherry picked from commit 93944711441c5d478e278f60eff659172f94b287)

5592ed76 fix-null-deref-window-under-pointer

Co-authored-by: Pranav Kunjir <[email protected]>

M  +6    -2    src/Platforms/ImagePlatformXcb.cpp

https://invent.kde.org/plasma/spectacle/-/commit/5f37568f34ead2a5abe9cf13fc0d36a69c66b9e2

diff --git a/src/Platforms/ImagePlatformXcb.cpp b/src/Platforms/ImagePlatformXcb.cpp
index 8da985265..179353f79 100644
--- a/src/Platforms/ImagePlatformXcb.cpp
+++ b/src/Platforms/ImagePlatformXcb.cpp
@@ -34,6 +34,7 @@
 #include <KWindowInfo>
 #include <KWindowSystem>
 #include <KX11Extras>
+#include <xcb/xproto.h>
 
 using namespace Qt::StringLiterals;
 
@@ -221,7 +222,7 @@ xcb_window_t ImagePlatformXcb::getWindowUnderCursor()
     XcbReplyPtr<xcb_intern_atom_reply_t> atomReply(xcb_intern_atom_reply(xcbConn, atomCookie, nullptr));
     XcbReplyPtr<xcb_query_pointer_reply_t> pointerReply(xcb_query_pointer_reply(xcbConn, pointerCookie, nullptr));
 
-    if (atomReply->atom == XCB_ATOM_NONE) {
+    if (!atomReply || !pointerReply || atomReply->atom == XCB_ATOM_NONE) {
         return QX11Info::appRootWindow();
     }
 
@@ -237,7 +238,7 @@ xcb_window_t ImagePlatformXcb::getWindowUnderCursor()
         auto propCookie = xcb_get_property_unchecked(xcbConn, 0, appWin, atomReply->atom, XCB_ATOM_ANY, 0, 0);
         XcbReplyPtr<xcb_get_property_reply_t> propReply(xcb_get_property_reply(xcbConn, propCookie, nullptr));
 
-        if (propReply->type != XCB_ATOM_NONE) {
+        if (propReply && propReply->type != XCB_ATOM_NONE) {
             return appWin;
         }
 
@@ -245,6 +246,9 @@ xcb_window_t ImagePlatformXcb::getWindowUnderCursor()
         // we should start looking at its children
         auto treeCookie = xcb_query_tree_unchecked(xcbConn, appWin);
         XcbReplyPtr<xcb_query_tree_reply_t> treeReply(xcb_query_tree_reply(xcbConn, treeCookie, nullptr));
+        if (!treeReply) {
+            continue;
+        }
         auto windowChildren = xcb_query_tree_children(treeReply.get());
         auto windowChildrenLength = xcb_query_tree_children_length(treeReply.get());