diff options
author | Simon Hausmann <simon.hausmann@qt.io> | 2017-08-23 11:08:50 +0200 |
---|---|---|
committer | Simon Hausmann <simon.hausmann@qt.io> | 2017-08-23 10:45:13 +0000 |
commit | b6c298d82293f2de3525cbbc6c26f94466bda034 (patch) | |
tree | d1eb645c1e56f1c66c270f01450fa19082fd72ba /src | |
parent | 941d820d7fe09ee9c1eeb10ddbba28eb45fd559f (diff) |
Fix memory corruption with type trimming
When creating a composite type, we register the meta-type in the qml
loader thread. However we would require linking of the compilation unit
to the QML/engine thread before we would be able to also undo that
registration in unlink(), because we require the engine member to be
set. If that did not happen, i.e. a qml type was loaded and trimmed from
the cache before it was ever linked, we would end up with a dangling
pointer in m_compositeTypes.
Let's handle the case of CompilationUnit referring to a QML composite
type separately from it being a compilation unit resulting from a .js
file or in a plain QJSEngine environment.
Task-number: QTBUG-62630
Change-Id: Ia68cc46f05345702bd9ba0378f61118f1964d141
Reviewed-by: Lars Knoll <lars.knoll@qt.io>
Diffstat (limited to 'src')
-rw-r--r-- | src/qml/compiler/qv4compileddata.cpp | 15 | ||||
-rw-r--r-- | src/qml/compiler/qv4compileddata_p.h | 3 | ||||
-rw-r--r-- | src/qml/qml/qqmlengine_p.h | 6 | ||||
-rw-r--r-- | src/qml/qml/qqmltypeloader.cpp | 2 |
4 files changed, 14 insertions, 12 deletions
diff --git a/src/qml/compiler/qv4compileddata.cpp b/src/qml/compiler/qv4compileddata.cpp index 8ca1a29b2a..32e8ee4da2 100644 --- a/src/qml/compiler/qv4compileddata.cpp +++ b/src/qml/compiler/qv4compileddata.cpp @@ -97,6 +97,7 @@ static QString cacheFilePath(const QUrl &url) CompilationUnit::CompilationUnit() : data(0) , engine(0) + , qmlEngine(0) , runtimeLookups(0) , runtimeRegularExpressions(0) , runtimeClasses(0) @@ -212,8 +213,8 @@ void CompilationUnit::unlink() if (isRegisteredWithEngine) { Q_ASSERT(data && quint32(propertyCaches.count()) > data->indexOfRootObject && propertyCaches.at(data->indexOfRootObject)); - if (engine) - QQmlEnginePrivate::get(engine)->unregisterInternalCompositeType(this); + if (qmlEngine) + qmlEngine->unregisterInternalCompositeType(this); QQmlMetaType::unregisterInternalCompositeType(this); isRegisteredWithEngine = false; } @@ -230,6 +231,7 @@ void CompilationUnit::unlink() resolvedTypes.clear(); engine = 0; + qmlEngine = 0; free(runtimeStrings); runtimeStrings = 0; delete [] runtimeLookups; @@ -259,9 +261,6 @@ void CompilationUnit::markObjects(QV4::ExecutionEngine *e) void CompilationUnit::destroy() { - QQmlEngine *qmlEngine = 0; - if (engine && engine->v8Engine) - qmlEngine = engine->v8Engine->engine(); if (qmlEngine) QQmlEnginePrivate::deleteInEngineThread(qmlEngine, this); else @@ -284,12 +283,14 @@ IdentifierHash<int> CompilationUnit::namedObjectsPerComponent(int componentObjec return *it; } -void CompilationUnit::finalize(QQmlEnginePrivate *engine) +void CompilationUnit::finalizeCompositeType(QQmlEnginePrivate *qmlEngine) { + this->qmlEngine = qmlEngine; + // Add to type registry of composites if (propertyCaches.needsVMEMetaObject(data->indexOfRootObject)) { QQmlMetaType::registerInternalCompositeType(this); - engine->registerInternalCompositeType(this); + qmlEngine->registerInternalCompositeType(this); } else { const QV4::CompiledData::Object *obj = objectAt(data->indexOfRootObject); auto *typeRef = resolvedTypes.value(obj->inheritedTypeNameIndex); diff --git a/src/qml/compiler/qv4compileddata_p.h b/src/qml/compiler/qv4compileddata_p.h index bca0dcdf8f..5d71bc4ac6 100644 --- a/src/qml/compiler/qv4compileddata_p.h +++ b/src/qml/compiler/qv4compileddata_p.h @@ -824,6 +824,7 @@ struct Q_QML_PRIVATE_EXPORT CompilationUnit : public CompilationUnitBase, public #ifndef V4_BOOTSTRAP ExecutionEngine *engine; + QQmlEnginePrivate *qmlEngine; // only used in QML environment for composite types, not in plain QJSEngine case. QString fileName() const { return data->stringAt(data->sourceFileIndex); } QUrl url() const { if (m_url.isNull) m_url = QUrl(fileName()); return m_url; } @@ -853,7 +854,7 @@ struct Q_QML_PRIVATE_EXPORT CompilationUnit : public CompilationUnitBase, public // pointers either to data->constants() or little-endian memory copy. const Value* constants; - void finalize(QQmlEnginePrivate *engine); + void finalizeCompositeType(QQmlEnginePrivate *qmlEngine); int totalBindingsCount; // Number of bindings used in this type int totalParserStatusCount; // Number of instantiated types that are QQmlParserStatus subclasses diff --git a/src/qml/qml/qqmlengine_p.h b/src/qml/qml/qqmlengine_p.h index da8ea24ea0..fd74a233a4 100644 --- a/src/qml/qml/qqmlengine_p.h +++ b/src/qml/qml/qqmlengine_p.h @@ -204,7 +204,7 @@ public: template<typename T> inline void deleteInEngineThread(T *); template<typename T> - inline static void deleteInEngineThread(QQmlEngine *, T *); + inline static void deleteInEngineThread(QQmlEnginePrivate *, T *); QString offlineStorageDatabaseDirectory() const; // These methods may be called from the loader thread @@ -359,10 +359,10 @@ Delete \a value in the \a engine thread. If the calling thread is the engine thread, \a value will be deleted immediately. */ template<typename T> -void QQmlEnginePrivate::deleteInEngineThread(QQmlEngine *engine, T *value) +void QQmlEnginePrivate::deleteInEngineThread(QQmlEnginePrivate *engine, T *value) { Q_ASSERT(engine); - QQmlEnginePrivate::get(engine)->deleteInEngineThread<T>(value); + engine->deleteInEngineThread<T>(value); } /*! diff --git a/src/qml/qml/qqmltypeloader.cpp b/src/qml/qml/qqmltypeloader.cpp index efa4ed2f79..84410875ab 100644 --- a/src/qml/qml/qqmltypeloader.cpp +++ b/src/qml/qml/qqmltypeloader.cpp @@ -2295,7 +2295,7 @@ void QQmlTypeData::done() } } - m_compiledData->finalize(enginePrivate); + m_compiledData->finalizeCompositeType(enginePrivate); } { |