From 1914f62c317075e30489701fd2efc87f3aa9367a Mon Sep 17 00:00:00 2001 From: Axel Spoerl Date: Wed, 29 Nov 2023 19:43:04 +0100 Subject: [PATCH] QMainWindowPrivate::layout - use QPointer instead of bare pointer qt_mainwindow_layout(mainWindow) returns the pointer to a stale object, if the layout has already been deleted. Most users of qt_mainwindow_layout() assert the returned pointer, or handle nullptr explicitly. If the mainwindow layout has already been deleted, they will still access it. While this has not lead to (known) issues yet, a UAF exception is thrown in an ASAN build. => Use a QPointer instead of a bare pointer. => Add missing nullptr check in QDockWidgetPrivate::endDrag() Pick-to: 6.6 6.5 Change-Id: I3484b53e0e2213b82085ceed3ffa66913947189f Reviewed-by: David Faure --- src/widgets/widgets/qdockwidget.cpp | 4 ++++ src/widgets/widgets/qmainwindow.cpp | 4 ++-- 2 files changed, 6 insertions(+), 2 deletions(-) diff --git a/src/widgets/widgets/qdockwidget.cpp b/src/widgets/widgets/qdockwidget.cpp index f76975859f4..a9b65a2e1c1 100644 --- a/src/widgets/widgets/qdockwidget.cpp +++ b/src/widgets/widgets/qdockwidget.cpp @@ -815,6 +815,10 @@ void QDockWidgetPrivate::endDrag(EndDragMode mode) Q_ASSERT(mainWindow != nullptr); QMainWindowLayout *mwLayout = qt_mainwindow_layout(mainWindow); + // if mainWindow is being deleted in an ongoing drag, make it a no-op instead of crashing + if (!mwLayout) + return; + if (mode == EndDragMode::Abort || !mwLayout->plug(state->widgetItem)) { if (hasFeature(this, QDockWidget::DockWidgetFloatable)) { // This QDockWidget will now stay in the floating state. diff --git a/src/widgets/widgets/qmainwindow.cpp b/src/widgets/widgets/qmainwindow.cpp index 662c9db8928..304682731a1 100644 --- a/src/widgets/widgets/qmainwindow.cpp +++ b/src/widgets/widgets/qmainwindow.cpp @@ -49,7 +49,7 @@ public: , useUnifiedToolBar(false) #endif { } - QMainWindowLayout *layout; + QPointer layout; QSize iconSize; bool explicitIconSize; Qt::ToolButtonStyle toolButtonStyle; @@ -60,7 +60,7 @@ public: static inline QMainWindowLayout *mainWindowLayout(const QMainWindow *mainWindow) { - return mainWindow ? mainWindow->d_func()->layout : static_cast(nullptr); + return mainWindow ? mainWindow->d_func()->layout.data() : static_cast(nullptr); } };