diff options
author | Fabian Kosmale <fabian.kosmale@qt.io> | 2022-11-07 15:52:54 +0100 |
---|---|---|
committer | Ulf Hermann <ulf.hermann@qt.io> | 2022-11-28 13:12:02 +0000 |
commit | 6cd8d209ec472a658a330f25b84f92cd61e0d4cf (patch) | |
tree | 790f8b6bf1074ab1e9b8d1bbb7f23ba2970b9c0b | |
parent | b6ba7e9c9023d1d5c6ba543c1c551344b7a9e5b5 (diff) |
Connections: Don't crash when target is deleted
Pick-to: 6.4 6.2
Fixes: QTBUG-108697
Change-Id: I019edf3a0a702ad1dca340473265933e4d131e99
Reviewed-by: Ulf Hermann <ulf.hermann@qt.io>
Reviewed-by: Fabian Kosmale <fabian.kosmale@qt.io>
-rw-r--r-- | src/qml/types/qqmlconnections.cpp | 14 | ||||
-rw-r--r-- | tests/auto/qml/qqmlconnections/data/invalidTarget.qml | 31 | ||||
-rw-r--r-- | tests/auto/qml/qqmlconnections/tst_qqmlconnections.cpp | 20 |
3 files changed, 57 insertions, 8 deletions
diff --git a/src/qml/types/qqmlconnections.cpp b/src/qml/types/qqmlconnections.cpp index e10327e240..1527a2ea34 100644 --- a/src/qml/types/qqmlconnections.cpp +++ b/src/qml/types/qqmlconnections.cpp @@ -24,15 +24,13 @@ Q_LOGGING_CATEGORY(lcQmlConnections, "qt.qml.connections") class QQmlConnectionsPrivate : public QObjectPrivate { public: - QQmlConnectionsPrivate() : target(nullptr), enabled(true), targetSet(false), ignoreUnknownSignals(false), componentcomplete(true) {} - QList<QQmlBoundSignal*> boundsignals; - QObject *target; + QQmlGuard<QObject> target; - bool enabled; - bool targetSet; - bool ignoreUnknownSignals; - bool componentcomplete; + bool enabled = true; + bool targetSet = false; + bool ignoreUnknownSignals = false; + bool componentcomplete = true; QQmlRefPointer<QV4::ExecutableCompilationUnit> compilationUnit; QList<const QV4::CompiledData::Binding *> bindings; @@ -119,7 +117,7 @@ QQmlConnections::QQmlConnections(QObject *parent) : QObject *QQmlConnections::target() const { Q_D(const QQmlConnections); - return d->targetSet ? d->target : parent(); + return d->targetSet ? d->target.data() : parent(); } class QQmlBoundSignalDeleter : public QObject diff --git a/tests/auto/qml/qqmlconnections/data/invalidTarget.qml b/tests/auto/qml/qqmlconnections/data/invalidTarget.qml new file mode 100644 index 0000000000..23599649ec --- /dev/null +++ b/tests/auto/qml/qqmlconnections/data/invalidTarget.qml @@ -0,0 +1,31 @@ +import QtQml + +QtObject { + id: root + objectName: button.objectName + + property QtObject b: QtObject { + objectName: "button" + id: button + signal clicked + } + + property Connections c: Connections { + id: connections + target: null + function onClicked() { button.destroy(); } + } + + property Timer t: Timer { + interval: 10 + running: true + onTriggered: { + root.objectName = connections.target.objectName + } + } + + Component.onCompleted: { + connections.target = button; + button.clicked() + } +} diff --git a/tests/auto/qml/qqmlconnections/tst_qqmlconnections.cpp b/tests/auto/qml/qqmlconnections/tst_qqmlconnections.cpp index dfc01df241..f23c474907 100644 --- a/tests/auto/qml/qqmlconnections/tst_qqmlconnections.cpp +++ b/tests/auto/qml/qqmlconnections/tst_qqmlconnections.cpp @@ -53,6 +53,7 @@ private slots: void noAcceleratedGlobalLookup(); void bindToPropertyWithUnderscoreChangeHandler(); + void invalidTarget(); private: QQmlEngine engine; @@ -465,6 +466,25 @@ void tst_qqmlconnections::bindToPropertyWithUnderscoreChangeHandler() QVERIFY(root->property("success").toBool()); } +void tst_qqmlconnections::invalidTarget() +{ + QQmlEngine engine; + const QUrl url = testFileUrl("invalidTarget.qml"); + QQmlComponent component(&engine, url); + QVERIFY2(component.isReady(), qPrintable(component.errorString())); + + QScopedPointer<QObject> root {component.create()}; + QVERIFY(root); + QCOMPARE(root->objectName(), QStringLiteral("button")); + + QTest::ignoreMessage( + QtWarningMsg, + qPrintable( + url.toString() + + QLatin1String(":5:5: TypeError: Cannot read property 'objectName' of null"))); + QTRY_VERIFY(root->objectName().isEmpty()); +} + QTEST_MAIN(tst_qqmlconnections) #include "tst_qqmlconnections.moc" |