diff options
author | Ulf Hermann <ulf.hermann@qt.io> | 2020-01-10 10:01:36 +0100 |
---|---|---|
committer | Ulf Hermann <ulf.hermann@qt.io> | 2020-01-10 11:07:10 +0100 |
commit | 3c23f5371a19991771bd29c27d377c6672e46cd1 (patch) | |
tree | 9ba6f841eb6799c279faf9eafb064fe7d9ce7ccd | |
parent | e5ddcab385f8dc0ad9dc2bcf3af1babeb4e0e569 (diff) |
On QQmlEngine destruction drop singletons before type loader
The singleton destruction can trigger additional types to be loaded.
Fixes: QTBUG-80840
Change-Id: Ifa406b2a1cfd3b9e9b36e8005dfc0808eebf15cf
Reviewed-by: Fabian Kosmale <fabian.kosmale@qt.io>
-rw-r--r-- | src/qml/qml/qqmlengine.cpp | 4 | ||||
-rw-r--r-- | tests/auto/qml/qqmlengine/data/evilSingletonInstantiation.qml | 6 | ||||
-rw-r--r-- | tests/auto/qml/qqmlengine/tst_qqmlengine.cpp | 31 |
3 files changed, 39 insertions, 2 deletions
diff --git a/src/qml/qml/qqmlengine.cpp b/src/qml/qml/qqmlengine.cpp index 2f4abca4b2..93964ac76f 100644 --- a/src/qml/qml/qqmlengine.cpp +++ b/src/qml/qml/qqmlengine.cpp @@ -1034,8 +1034,6 @@ QQmlEngine::~QQmlEngine() Q_D(QQmlEngine); QJSEnginePrivate::removeFromDebugServer(this); - d->typeLoader.invalidate(); - // Emit onDestruction signals for the root context before // we destroy the contexts, engine, Singleton Types etc. that // may be required to handle the destruction signal. @@ -1051,6 +1049,8 @@ QQmlEngine::~QQmlEngine() delete d->rootContext; d->rootContext = nullptr; + + d->typeLoader.invalidate(); } /*! \fn void QQmlEngine::quit() diff --git a/tests/auto/qml/qqmlengine/data/evilSingletonInstantiation.qml b/tests/auto/qml/qqmlengine/data/evilSingletonInstantiation.qml new file mode 100644 index 0000000000..757b0c90bb --- /dev/null +++ b/tests/auto/qml/qqmlengine/data/evilSingletonInstantiation.qml @@ -0,0 +1,6 @@ +import QtQml 2.12 +import foo.foo 1.0 + +QtObject { + objectName: Singleton.objectName +} diff --git a/tests/auto/qml/qqmlengine/tst_qqmlengine.cpp b/tests/auto/qml/qqmlengine/tst_qqmlengine.cpp index 64f167b47e..613616ab71 100644 --- a/tests/auto/qml/qqmlengine/tst_qqmlengine.cpp +++ b/tests/auto/qml/qqmlengine/tst_qqmlengine.cpp @@ -83,6 +83,7 @@ private slots: void singletonInstance(); void aggressiveGc(); void cachedGetterLookup_qtbug_75335(); + void createComponentOnSingletonDestruction(); public slots: QObject *createAQObjectForOwnershipTest () @@ -1141,6 +1142,36 @@ void tst_qqmlengine::cachedGetterLookup_qtbug_75335() QVERIFY(object != nullptr); } +class EvilSingleton : public QObject +{ + Q_OBJECT +public: + QPointer<QQmlEngine> m_engine; + EvilSingleton(QQmlEngine *engine) : m_engine(engine) { + connect(this, &QObject::destroyed, this, [this]() { + QQmlComponent component(m_engine); + component.setData("import QtQml 2.0\nQtObject {}", QUrl("file://Stuff.qml")); + QVERIFY(component.isReady()); + QScopedPointer<QObject> obj(component.create()); + QVERIFY(obj); + }); + } +}; + +void tst_qqmlengine::createComponentOnSingletonDestruction() +{ + qmlRegisterSingletonType<EvilSingleton>("foo.foo", 1, 0, "Singleton", + [](QQmlEngine *engine, QJSEngine *) { + return new EvilSingleton(engine); + }); + + QQmlEngine engine; + QQmlComponent component(&engine, testFileUrl("evilSingletonInstantiation.qml")); + QVERIFY(component.isReady()); + QScopedPointer<QObject> obj(component.create()); + QVERIFY(obj); +} + QTEST_MAIN(tst_qqmlengine) #include "tst_qqmlengine.moc" |