diff options
author | Simon Hausmann <[email protected]> | 2014-06-20 17:26:57 +0200 |
---|---|---|
committer | Simon Hausmann <[email protected]> | 2014-06-23 19:17:22 +0200 |
commit | 195b998175b629e6e915588e66991f74cffa4e48 (patch) | |
tree | 2e77a4a6cb645e6548daf6382ee85a68f3ea93e8 | |
parent | 714d9d95484907378b46292df7aec0832f557f1d (diff) |
Fix crash when deleting component in Component.onComplete through loader
This is a regression introduced with Qt 5.3.0. The recursion watcher code that
is supposed to handle the test case of QTBUG-39775 can detect the recursion
into the object creator. However the boolean that indicates the recursion is a
member of a structure that's deleted afterwards. To avoid access to deleted
memory, this patch simply reference counts data structure shared between the
creators and also wraps the recursion watcher into a convenience class that
also increases/decreases the reference count accordingly.
Change-Id: I8d2e3e200ab1295e89d951e09f187d382a056d5a
Task-number: QTBUG-39775
Reviewed-by: Lars Knoll <[email protected]>
-rw-r--r-- | src/qml/qml/qqmlobjectcreator.cpp | 17 | ||||
-rw-r--r-- | src/qml/qml/qqmlobjectcreator_p.h | 18 |
2 files changed, 28 insertions, 7 deletions
diff --git a/src/qml/qml/qqmlobjectcreator.cpp b/src/qml/qml/qqmlobjectcreator.cpp index 16c9dd7aa0..36c7dfb0e9 100644 --- a/src/qml/qml/qqmlobjectcreator.cpp +++ b/src/qml/qml/qqmlobjectcreator.cpp @@ -91,7 +91,7 @@ QQmlObjectCreator::QQmlObjectCreator(QQmlContextData *parentContext, QQmlCompile init(parentContext); sharedState = new QQmlObjectCreatorSharedState; - sharedState.setFlag(); // We own it, so we must delete it + topLevelCreator = true; sharedState->componentAttached = 0; sharedState->allCreatedBindings.allocate(compiledData->totalBindingsCount); sharedState->allParserStatusCallbacks.allocate(compiledData->totalParserStatusCount); @@ -115,6 +115,7 @@ QQmlObjectCreator::QQmlObjectCreator(QQmlContextData *parentContext, QQmlCompile init(parentContext); sharedState = inheritedSharedState; + topLevelCreator = false; } void QQmlObjectCreator::init(QQmlContextData *providedParentContext) @@ -139,9 +140,9 @@ void QQmlObjectCreator::init(QQmlContextData *providedParentContext) QQmlObjectCreator::~QQmlObjectCreator() { - if (sharedState.flag()) { + if (topLevelCreator) { { - QRecursionWatcher<QQmlObjectCreatorSharedState, &QQmlObjectCreatorSharedState::recursionNode> watcher(sharedState.data()); + QQmlObjectCreatorRecursionWatcher watcher(this); } for (int i = 0; i < sharedState->allCreatedBindings.count(); ++i) { QQmlAbstractBinding *b = sharedState->allCreatedBindings.at(i); @@ -157,7 +158,6 @@ QQmlObjectCreator::~QQmlObjectCreator() QQmlComponentAttached *a = sharedState->componentAttached; a->rem(); } - delete sharedState.data(); } } @@ -1172,7 +1172,7 @@ QQmlContextData *QQmlObjectCreator::finalize(QQmlInstantiationInterrupt &interru Q_ASSERT(phase == ObjectsCreated || phase == Finalizing); phase = Finalizing; - QRecursionWatcher<QQmlObjectCreatorSharedState, &QQmlObjectCreatorSharedState::recursionNode> watcher(sharedState.data()); + QQmlObjectCreatorRecursionWatcher watcher(this); ActiveOCRestorer ocRestorer(this, QQmlEnginePrivate::get(engine)); { @@ -1334,3 +1334,10 @@ bool QQmlObjectCreator::populateInstance(int index, QObject *instance, QObject * } + + +QQmlObjectCreatorRecursionWatcher::QQmlObjectCreatorRecursionWatcher(QQmlObjectCreator *creator) + : sharedState(creator->sharedState) + , watcher(creator->sharedState.data()) +{ +} diff --git a/src/qml/qml/qqmlobjectcreator_p.h b/src/qml/qml/qqmlobjectcreator_p.h index 379a3b2970..ad2d67624f 100644 --- a/src/qml/qml/qqmlobjectcreator_p.h +++ b/src/qml/qml/qqmlobjectcreator_p.h @@ -57,7 +57,7 @@ struct QQmlTypeCompiler; class QQmlInstantiationInterrupt; struct QQmlVmeProfiler; -struct QQmlObjectCreatorSharedState +struct QQmlObjectCreatorSharedState : public QSharedData { QQmlContextData *rootContext; QQmlContextData *creationContext; @@ -128,7 +128,8 @@ private: const QVector<QQmlPropertyCache *> &propertyCaches; const QVector<QByteArray> &vmeMetaObjectData; QHash<int, int> objectIndexToId; - QFlagPointer<QQmlObjectCreatorSharedState> sharedState; + QExplicitlySharedDataPointer<QQmlObjectCreatorSharedState> sharedState; + bool topLevelCreator; void *activeVMEDataForRootContext; QObject *_qobject; @@ -142,6 +143,19 @@ private: QQmlVMEMetaObject *_vmeMetaObject; QQmlListProperty<void> _currentList; QV4::ExecutionContext *_qmlContext; + + friend struct QQmlObjectCreatorRecursionWatcher; +}; + +struct QQmlObjectCreatorRecursionWatcher +{ + QQmlObjectCreatorRecursionWatcher(QQmlObjectCreator *creator); + + bool hasRecursed() const { return watcher.hasRecursed(); } + +private: + QExplicitlySharedDataPointer<QQmlObjectCreatorSharedState> sharedState; + QRecursionWatcher<QQmlObjectCreatorSharedState, &QQmlObjectCreatorSharedState::recursionNode> watcher; }; QT_END_NAMESPACE |