summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorMarc Mutz <[email protected]>2025-03-26 15:03:43 +0100
committerMarc Mutz <[email protected]>2025-03-28 01:50:59 +0000
commit6ac40faa80ed2faf92ec95759baf2fde7697c207 (patch)
treefbf921b0b114196c369ec9ae70a02f5877b2df08
parentffb81e62704f72b61ead213abed708008762004f (diff)
QXcbDrag: Fix UB (unaligned load) in handleFinished()
According to the XDND spec¹, the window-ID of an XcbFinished message is in xclient.l[0]. That's Xlib terms, though. In xcb terms, it's in xcb_client_message_event_t's data.data32[0]. This is how all QXcbDrag functions handle it (e.g. move()), except handleFinished(), which casts the uint32_t array to a (misaligned) ulong one. ¹ https://www.freedesktop.org/wiki/Specifications/XDND/#index29h3 (the fragment doesn't look like it's stable, it's the section titled "XdndFinished (new in version 2)") Says UBSan: qxcbdrag.cpp:1051:12: runtime error: load of misaligned address 0x60400078ba9c for type 'const long unsigned int', which requires 8 byte alignment 0x60400078ba9c: note: pointer points here c0 01 00 00 28 02 e0 08 01 00 00 00 c8 01 00 00 00 00 00 00 00 00 00 00 93 23 00 00 00 00 00 00 ^ #0 0x7fa3ea3a957c in QXcbDrag::handleFinished(xcb_client_message_event_t const*) qxcbdrag.cpp:1051 #1 0x7fa3e9e20dec in QXcbConnection::handleXcbEvent(xcb_generic_event_t*) qxcbconnection.cpp:607 [...] I have a hard time seeing how it could have worked in big-endian systems. In LE ones, it only works because the high bits of l[0], which come from data32[1], are stripped again when the value is narrowed for passing to findTransactionByWindow(). But the 'if' before _could_ mis-detect a zero xcb_window_t for a non-zero one if data32[1] wasn't empty... To summarize: this is a mess (that's a technical term). Fix by removing the pointless cast, and just read data32[0], like elsewhere in the file. Amends c3f9de62966d32d8e33d62eb374fe2657a4cfebe(!). Pick-to: 6.9 6.8 6.5 5.15 Fixes: QTBUG-127517 Change-Id: Ie7c3718bada52ff82c16f814eee8ec57248fbfbf Reviewed-by: Liang Qi <[email protected]>
-rw-r--r--src/plugins/platforms/xcb/qxcbdrag.cpp5
1 files changed, 2 insertions, 3 deletions
diff --git a/src/plugins/platforms/xcb/qxcbdrag.cpp b/src/plugins/platforms/xcb/qxcbdrag.cpp
index b6f38d6592e..a60933755be 100644
--- a/src/plugins/platforms/xcb/qxcbdrag.cpp
+++ b/src/plugins/platforms/xcb/qxcbdrag.cpp
@@ -1047,9 +1047,8 @@ void QXcbDrag::handleFinished(const xcb_client_message_event_t *event)
if (event->window != connection()->qtSelectionOwner())
return;
- const unsigned long *l = (const unsigned long *)event->data.data32;
- if (l[0]) {
- int at = findTransactionByWindow(l[0]);
+ if (xcb_window_t w = event->data.data32[0]) {
+ int at = findTransactionByWindow(w);
if (at != -1) {
Transaction t = transactions.takeAt(at);