From 6a84a51611f69f3641ae47bbd7b6bd5266ae88ef Mon Sep 17 00:00:00 2001
From: Gabriel de Dietrich <gabriel.dedietrich@theqtcompany.com>
Date: Wed, 6 Apr 2016 10:51:55 -0700
Subject: [PATCH] QWidgetWindow: Guard reference to own widget

~QWidgetPrivate() may end up calling QWidgetPrivate::
deleteTLSysExtra() which, in turn, calls QWindow::destroy().
This sends an event to the window itself. This reaches
QWidgetWindow::event() which will forward the event to
the widget. However, the widget has just been deleted
since the sequence was initiated by ~QObject().

Task-number: QTBUG-53103
Change-Id: Ib511714a76bbc1e734d6f2800a983eb1459bbf0b
Reviewed-by: Marc Mutz <marc.mutz@kdab.com>
Reviewed-by: Friedemann Kleint <Friedemann.Kleint@qt.io>
---
 src/widgets/kernel/qwidgetwindow.cpp | 7 +++++--
 src/widgets/kernel/qwidgetwindow_p.h | 2 +-
 2 files changed, 6 insertions(+), 3 deletions(-)

diff --git a/src/widgets/kernel/qwidgetwindow.cpp b/src/widgets/kernel/qwidgetwindow.cpp
index b638c6c377d..ec2618e5013 100644
--- a/src/widgets/kernel/qwidgetwindow.cpp
+++ b/src/widgets/kernel/qwidgetwindow.cpp
@@ -123,7 +123,7 @@ QWidgetWindow::QWidgetWindow(QWidget *widget)
         && !QApplication::testAttribute(Qt::AA_ForceRasterWidgets)) {
         setSurfaceType(QSurface::RasterGLSurface);
     }
-    connect(m_widget, &QObject::objectNameChanged, this, &QWidgetWindow::updateObjectName);
+    connect(widget, &QObject::objectNameChanged, this, &QWidgetWindow::updateObjectName);
     connect(this, SIGNAL(screenChanged(QScreen*)), this, SLOT(handleScreenChange()));
 }
 
@@ -174,6 +174,9 @@ static inline bool shouldBePropagatedToWidget(QEvent *event)
 
 bool QWidgetWindow::event(QEvent *event)
 {
+    if (!m_widget)
+        return QWindow::event(event);
+
     if (m_widget->testAttribute(Qt::WA_DontShowOnScreen)) {
         // \a event is uninteresting for QWidgetWindow, the event was probably
         // generated before WA_DontShowOnScreen was set
@@ -375,7 +378,7 @@ void QWidgetWindow::handleEnterLeaveEvent(QEvent *event)
     } else {
         const QEnterEvent *ee = static_cast<QEnterEvent *>(event);
         QWidget *child = m_widget->childAt(ee->pos());
-        QWidget *receiver = child ? child : m_widget;
+        QWidget *receiver = child ? child : m_widget.data();
         QApplicationPrivate::dispatchEnterLeave(receiver, 0, ee->screenPos());
         qt_last_mouse_receiver = receiver;
     }
diff --git a/src/widgets/kernel/qwidgetwindow_p.h b/src/widgets/kernel/qwidgetwindow_p.h
index ca4bac8d865..7fafb01b3d6 100644
--- a/src/widgets/kernel/qwidgetwindow_p.h
+++ b/src/widgets/kernel/qwidgetwindow_p.h
@@ -119,7 +119,7 @@ private:
     };
     QWidget *getFocusWidget(FocusWidgets fw);
 
-    QWidget *m_widget;
+    QPointer<QWidget> m_widget;
     QPointer<QWidget> m_implicit_mouse_grabber;
 #ifndef QT_NO_DRAGANDDROP
     QPointer<QWidget> m_dragTarget;
-- 
GitLab