aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorPaul Olav Tvete <paul.tvete@qt.io>2024-02-26 12:29:46 +0100
committerQt Cherry-pick Bot <cherrypick_bot@qt-project.org>2024-03-05 02:45:18 +0000
commit2cf35d3f46810233396bd560a5e263857732b227 (patch)
treedcb7a9462aa8a02cf56f93ab25e2014d9bd66343
parent9580f7970cc394e2a499a3b5b65d3391b5bb6442 (diff)
Fix crash when item is deleted in event handler
QQuickDeliveryAgentPrivate::deliverPressOrReleaseEvent() creates a list of possible targets and iterates over it. This would cause a read of deleted memory if delivery to one target would cause another item in the list to be deleted. Fixes: QTBUG-91272 Pick-to: 6.5 Change-Id: I3f648e683d9b441ee0f14e4f721338ac59ace3cc Reviewed-by: Volker Hilsheimer <volker.hilsheimer@qt.io> (cherry picked from commit 10536ea75063210e78563e35e4ad3a755b172530) Reviewed-by: Qt Cherry-pick Bot <cherrypick_bot@qt-project.org> (cherry picked from commit 9c9072e82fe531a0a5b70ac7b914e9e1099248d4)
-rw-r--r--src/quick/util/qquickdeliveryagent.cpp6
-rw-r--r--tests/auto/quick/qquickdeliveryagent/tst_qquickdeliveryagent.cpp34
2 files changed, 39 insertions, 1 deletions
diff --git a/src/quick/util/qquickdeliveryagent.cpp b/src/quick/util/qquickdeliveryagent.cpp
index d9b071e85b..6223403bc1 100644
--- a/src/quick/util/qquickdeliveryagent.cpp
+++ b/src/quick/util/qquickdeliveryagent.cpp
@@ -2115,7 +2115,11 @@ bool QQuickDeliveryAgentPrivate::deliverPressOrReleaseEvent(QPointerEvent *event
}
}
- for (QQuickItem *item : targetItems) {
+ QVector<QPointer<QQuickItem>> safeTargetItems(targetItems.begin(), targetItems.end());
+
+ for (auto &item : safeTargetItems) {
+ if (item.isNull())
+ continue;
// failsafe: when items get into a subscene somehow, ensure that QQuickItemPrivate::deliveryAgent() can find it
if (isSubsceneAgent)
QQuickItemPrivate::get(item)->maybeHasSubsceneDeliveryAgent = true;
diff --git a/tests/auto/quick/qquickdeliveryagent/tst_qquickdeliveryagent.cpp b/tests/auto/quick/qquickdeliveryagent/tst_qquickdeliveryagent.cpp
index a9ef64a324..5035b9b6ce 100644
--- a/tests/auto/quick/qquickdeliveryagent/tst_qquickdeliveryagent.cpp
+++ b/tests/auto/quick/qquickdeliveryagent/tst_qquickdeliveryagent.cpp
@@ -19,6 +19,7 @@
#include <QtQuickTestUtils/private/qmlutils_p.h>
#include <QtQuickTestUtils/private/visualtestutils_p.h>
#include <QtQuickTestUtils/private/viewtestutils_p.h>
+#include <QtQuick/private/qquickmousearea_p.h>
#include <QtGui/private/qeventpoint_p.h>
@@ -141,6 +142,7 @@ private slots:
void hoverEnterOnItemMove();
void hoverEnterOnItemMoveAfterHide();
void clearItemsOnHoverLeave();
+ void deleteTargetOnPress();
private:
QScopedPointer<QPointingDevice> touchDevice = QScopedPointer<QPointingDevice>(QTest::createTouchDevice());
@@ -594,6 +596,38 @@ void tst_qquickdeliveryagent::clearItemsOnHoverLeave()
QTest::mouseMove(&window, QPoint(10, 405)); // Exit MouseArea that triggers close.
}
+// QTBUG-91272
+void tst_qquickdeliveryagent::deleteTargetOnPress()
+{
+ QQuickWindow window;
+ auto deliveryAgent = QQuickWindowPrivate::get(&window)->deliveryAgentPrivate();
+ window.resize(200, 200);
+ window.show();
+ QVERIFY(QTest::qWaitForWindowExposed(&window));
+
+ QQuickMouseArea *lowerArea = new QQuickMouseArea(window.contentItem());
+ lowerArea->setWidth(200);
+ lowerArea->setHeight(200);
+
+ QQuickMouseArea *upperArea = new QQuickMouseArea(window.contentItem());
+ upperArea->setWidth(180);
+ upperArea->setHeight(180);
+ bool pressed = false;
+ connect(upperArea, &QQuickMouseArea::pressed, this, [&]() {
+ pressed = true;
+ delete lowerArea;
+ lowerArea = nullptr;
+ });
+ QTest::mouseMove(&window, QPoint(100, 100));
+ QTest::mousePress(&window, Qt::MouseButton::LeftButton, {}, {100, 100});
+ deliveryAgent->flushFrameSynchronousEvents(&window);
+ QVERIFY(pressed);
+ QVERIFY(upperArea->isPressed());
+ QTest::mouseRelease(&window, Qt::MouseButton::LeftButton, {}, {100, 100});
+ deliveryAgent->flushFrameSynchronousEvents(&window);
+ QVERIFY(!upperArea->isPressed());
+}
+
QTEST_MAIN(tst_qquickdeliveryagent)
#include "tst_qquickdeliveryagent.moc"