Drag'n'Drop: fix crash when widgets are destroyed during event handling

Widgets might be destroyed when handling a dragMoveEvent, in which case
the following code will operate on dangling pointers or null pointers.
Use a QPointer to watch for the original event receiver to disappear,
and add the necessary checks for the objects we deliver events to being
null.

Change-Id: I4ca2f182540ae21113f4bea4e5c569e983cc58bf
Fixes: QTBUG-78907
Reviewed-by: Gatis Paeglis <gatis.paeglis@qt.io>
This commit is contained in:
Volker Hilsheimer 2019-10-08 10:56:44 +02:00 committed by Shawn Rutledge
parent 9845c06d1f
commit 3dbc7596a3

View File

@ -885,7 +885,7 @@ void QWidgetWindow::handleDragEnterEvent(QDragEnterEvent *event, QWidget *widget
void QWidgetWindow::handleDragMoveEvent(QDragMoveEvent *event)
{
auto *widget = findDnDTarget(m_widget, event->pos());
QPointer<QWidget> widget = findDnDTarget(m_widget, event->pos());
if (!widget) {
event->ignore();
if (m_dragTarget) { // Send DragLeave to previous
@ -908,14 +908,18 @@ void QWidgetWindow::handleDragMoveEvent(QDragMoveEvent *event)
QGuiApplication::forwardEvent(m_dragTarget, &leaveEvent, event);
m_dragTarget = nullptr;
}
// Send DragEnter to new widget.
handleDragEnterEvent(static_cast<QDragEnterEvent*>(event), widget);
// Handling 'DragEnter' should suffice for the application.
translated.setDropAction(event->dropAction());
translated.setAccepted(event->isAccepted());
// The drag enter event is always immediately followed by a drag move event,
// see QDragEnterEvent documentation.
QGuiApplication::forwardEvent(m_dragTarget, &translated, event);
// widget might have been deleted when handling the leaveEvent
if (widget) {
// Send DragEnter to new widget.
handleDragEnterEvent(static_cast<QDragEnterEvent*>(event), widget);
// Handling 'DragEnter' should suffice for the application.
translated.setDropAction(event->dropAction());
translated.setAccepted(event->isAccepted());
// The drag enter event is always immediately followed by a drag move event,
// see QDragEnterEvent documentation.
if (m_dragTarget)
QGuiApplication::forwardEvent(m_dragTarget, &translated, event);
}
}
event->setAccepted(translated.isAccepted());
event->setDropAction(translated.dropAction());