From 127659c45020a83b80eeed7106c1f377a36c5c77 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Morten=20Johan=20S=C3=B8rvig?= Date: Tue, 24 Apr 2018 12:46:44 +0200 Subject: =?UTF-8?q?QQuickWindow:=20Don=E2=80=99t=20crash=20on=20events=20d?= =?UTF-8?q?uring=20destruction?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Deleting d->contentItem may call into the platform plugin, for example if the contentItem is a Window. This can again make the platform (plugin) generate events for the QQuickWindow that is being destroyed. The QQuickWindow may try to use the now invalid d->contentItem during event processing, and crash. This is especially prone to happening if/when the platform plugin does less queuing of events, for example on macOS after commit ed483346. Fix this by clearing the d->contentItem pointer before deleting it. Also make sure all d->contentItem accesses have nullptr checks. Task-number: QTBUG-67802 Change-Id: Ieff97711fbe15818948d4b6ade069b096a55c683 Reviewed-by: Tor Arne Vestbø Reviewed-by: Simon Hausmann --- src/quick/items/qquickwindow.cpp | 21 +++++++++++++++------ 1 file changed, 15 insertions(+), 6 deletions(-) (limited to 'src/quick/items/qquickwindow.cpp') diff --git a/src/quick/items/qquickwindow.cpp b/src/quick/items/qquickwindow.cpp index 48eba6a7a0..b0b747a5eb 100644 --- a/src/quick/items/qquickwindow.cpp +++ b/src/quick/items/qquickwindow.cpp @@ -256,14 +256,16 @@ void QQuickWindow::hideEvent(QHideEvent *) void QQuickWindow::focusOutEvent(QFocusEvent *ev) { Q_D(QQuickWindow); - d->contentItem->setFocus(false, ev->reason()); + if (d->contentItem) + d->contentItem->setFocus(false, ev->reason()); } /*! \reimp */ void QQuickWindow::focusInEvent(QFocusEvent *ev) { Q_D(QQuickWindow); - d->contentItem->setFocus(true, ev->reason()); + if (d->contentItem) + d->contentItem->setFocus(true, ev->reason()); d->updateFocusItemTransform(); } @@ -1315,7 +1317,9 @@ QQuickWindow::~QQuickWindow() #if QT_CONFIG(draganddrop) delete d->dragGrabber; d->dragGrabber = nullptr; #endif - delete d->contentItem; d->contentItem = nullptr; + QQuickRootItem *root = d->contentItem; + d->contentItem = nullptr; + delete root; qDeleteAll(d->pointerEventInstances); d->pointerEventInstances.clear(); @@ -1571,6 +1575,8 @@ bool QQuickWindow::event(QEvent *e) return d->deliverTouchCancelEvent(static_cast(e)); break; case QEvent::Enter: { + if (!d->contentItem) + return false; QEnterEvent *enter = static_cast(e); bool accepted = enter->isAccepted(); bool delivered = d->deliverHoverEvent(d->contentItem, enter->windowPos(), d->lastMousePosition, @@ -1592,7 +1598,8 @@ bool QQuickWindow::event(QEvent *e) break; #endif case QEvent::WindowDeactivate: - contentItem()->windowDeactivateEvent(); + if (d->contentItem) + d->contentItem->windowDeactivateEvent(); break; case QEvent::Close: { // TOOD Qt 6 (binary incompatible) @@ -1617,7 +1624,8 @@ bool QQuickWindow::event(QEvent *e) } #if QT_CONFIG(gestures) case QEvent::NativeGesture: - d->deliverNativeGestureEvent(d->contentItem, static_cast(e)); + if (d->contentItem) + d->deliverNativeGestureEvent(d->contentItem, static_cast(e)); break; #endif case QEvent::ShortcutOverride: @@ -1937,7 +1945,8 @@ void QQuickWindow::wheelEvent(QWheelEvent *event) return; event->ignore(); - d->deliverWheelEvent(d->contentItem, event); + if (d->contentItem) + d->deliverWheelEvent(d->contentItem, event); d->lastWheelEventAccepted = event->isAccepted(); } #endif // wheelevent -- cgit v1.2.3