aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorFabian Kosmale <fabian.kosmale@qt.io>2022-11-07 15:52:54 +0100
committerUlf Hermann <ulf.hermann@qt.io>2022-11-28 13:12:02 +0000
commit6cd8d209ec472a658a330f25b84f92cd61e0d4cf (patch)
tree790f8b6bf1074ab1e9b8d1bbb7f23ba2970b9c0b
parentb6ba7e9c9023d1d5c6ba543c1c551344b7a9e5b5 (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.cpp14
-rw-r--r--tests/auto/qml/qqmlconnections/data/invalidTarget.qml31
-rw-r--r--tests/auto/qml/qqmlconnections/tst_qqmlconnections.cpp20
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"