diff options
author | Ulf Hermann <ulf.hermann@qt.io> | 2023-06-14 10:54:50 +0200 |
---|---|---|
committer | Ulf Hermann <ulf.hermann@qt.io> | 2023-06-15 11:57:32 +0000 |
commit | a2104034d404179f5fad98fd54a133b288ded47d (patch) | |
tree | 7efcd2510ce8481a0e14ac6a665c0f384889ad61 /src/qml/qml/qqmlglobal.cpp | |
parent | 0c50edd6f5a819a7bc6e19c5ac69191d491167da (diff) |
QML: Try QML conversion before metatype conversion
and guard against null gadgetPtr. This is what we get for uninitialized
value type properties.
Pick-to: 6.5 6.5.2 6.6
Fixes: QTBUG-114494
Change-Id: I86ad23abcc4fec219017d1aad6b7add1c9a9af5d
Reviewed-by: Fabian Kosmale <fabian.kosmale@qt.io>
Diffstat (limited to 'src/qml/qml/qqmlglobal.cpp')
-rw-r--r-- | src/qml/qml/qqmlglobal.cpp | 86 |
1 files changed, 46 insertions, 40 deletions
diff --git a/src/qml/qml/qqmlglobal.cpp b/src/qml/qml/qqmlglobal.cpp index e2ca8f873f..3759983b7a 100644 --- a/src/qml/qml/qqmlglobal.cpp +++ b/src/qml/qml/qqmlglobal.cpp @@ -115,30 +115,33 @@ static bool fromMatchingType( const QMetaType parameterType = ctor.parameterMetaType(0); - QVariant source = retrieve(parameterType); - const QMetaType sourceMetaType = source.metaType(); - if (sourceMetaType == parameterType) { - callConstructor(targetMetaObject, i, source.data(), allocate()); - return true; - } - - if (const QMetaObject *parameterMetaObject = parameterType.metaObject()) { - if (const QMetaObject *sourceMetaObject = sourceMetaType.metaObject(); - sourceMetaObject && sourceMetaObject->inherits(parameterMetaObject)) { - // Allow construction from derived types. - callConstructor(targetMetaObject, i, source.data(), allocate()); + if (retrieve(parameterType, [&](QMetaType sourceMetaType, void *sourceData) { + if (sourceMetaType == parameterType) { + callConstructor(targetMetaObject, i, sourceData, allocate()); return true; } - } - // Do not recursively try to create parameters here. This may end up in infinite recursion. + if (const QMetaObject *parameterMetaObject = parameterType.metaObject()) { + if (const QMetaObject *sourceMetaObject = sourceMetaType.metaObject(); + sourceMetaObject && sourceMetaObject->inherits(parameterMetaObject)) { + // Allow construction from derived types. + callConstructor(targetMetaObject, i, sourceData, allocate()); + return true; + } + } + + // Do not recursively try to create parameters here. This may end up in infinite recursion. - // At this point, s should be a builtin type. For builtin types - // the QMetaType converters are good enough. - QVariant converted(parameterType); - if (QMetaType::convert(sourceMetaType, source.constData(), - parameterType, converted.data())) { - callConstructor(targetMetaObject, i, converted.data(), allocate()); + // At this point, s should be a builtin type. For builtin types + // the QMetaType converters are good enough. + QVariant converted(parameterType); + if (QMetaType::convert(sourceMetaType, sourceData, parameterType, converted.data())) { + callConstructor(targetMetaObject, i, converted.data(), allocate()); + return true; + } + + return false; + })) { return true; } } @@ -151,8 +154,10 @@ static bool fromMatchingType( const QMetaObject *targetMetaObject, const QV4::Value &source, Allocate &&allocate) { return fromMatchingType( - targetMetaObject, std::forward<Allocate>(allocate), [&](QMetaType parameterType) { - return QV4::ExecutionEngine::toVariant(source, parameterType); + targetMetaObject, std::forward<Allocate>(allocate), + [&](QMetaType parameterType, auto callback) { + QVariant variant = QV4::ExecutionEngine::toVariant(source, parameterType); + return callback(variant.metaType(), variant.data()); }); } @@ -160,8 +165,9 @@ template<typename Allocate> static bool fromMatchingType( const QMetaObject *targetMetaObject, QVariant source, Allocate &&allocate) { - return fromMatchingType(targetMetaObject, std::forward<Allocate>(allocate), [&](QMetaType) { - return source; + return fromMatchingType(targetMetaObject, std::forward<Allocate>(allocate), + [&](QMetaType, auto callback) { + return callback(source.metaType(), source.data()); }); } @@ -491,12 +497,12 @@ bool QQmlValueTypeProvider::createValueType( } bool QQmlValueTypeProvider::createValueType( - QMetaType targetMetaType, void *target, const QVariant &source) + QMetaType targetMetaType, void *target, QMetaType sourceMetaType, void *source) { - if (source.metaType() == QMetaType::fromType<QJSValue>()) { - QJSValue val = source.value<QJSValue>(); + if (sourceMetaType == QMetaType::fromType<QJSValue>()) { + const QJSValue *val = static_cast<const QJSValue *>(source); return createValueType( - targetMetaType, target, QV4::Value(QJSValuePrivate::asReturnedValue(&val))); + targetMetaType, target, QV4::Value(QJSValuePrivate::asReturnedValue(val))); } if (!isConstructibleMetaType(targetMetaType)) @@ -518,39 +524,39 @@ bool QQmlValueTypeProvider::createValueType( if (type.canPopulateValueType()) { if (const QMetaObject *sourceMetaObject - = QQmlMetaType::metaObjectForValueType(source.metaType())) { + = QQmlMetaType::metaObjectForValueType(sourceMetaType)) { doWriteProperties( targetMetaObject, target, sourceMetaObject, [&source](const QMetaObject *sourceMetaObject, int sourceProperty) { - return sourceMetaObject->property(sourceProperty).readOnGadget( - source.constData()); + return sourceMetaObject->property(sourceProperty).readOnGadget(source); }); return true; } - if (source.metaType() == QMetaType::fromType<QVariantMap>()) { + if (sourceMetaType == QMetaType::fromType<QVariantMap>()) { doWriteProperties( - targetMetaObject, target, - *static_cast<const QVariantMap *>(source.constData())); + targetMetaObject, target, *static_cast<const QVariantMap *>(source)); return true; } - if (source.metaType() == QMetaType::fromType<QVariantHash>()) { + if (sourceMetaType == QMetaType::fromType<QVariantHash>()) { doWriteProperties( - targetMetaObject, target, - *static_cast<const QVariantHash *>(source.constData())); + targetMetaObject, target, *static_cast<const QVariantHash *>(source)); return true; } - if (source.metaType().flags() & QMetaType::PointerToQObject) { - doWriteProperties(targetMetaObject, target, source.value<QObject *>()); + if (sourceMetaType.flags() & QMetaType::PointerToQObject) { + doWriteProperties(targetMetaObject, target, *static_cast<QObject *const *>(source)); return true; } } if (type.canConstructValueType()) { - if (fromMatchingType(targetMetaObject, source, destruct)) + if (fromMatchingType(targetMetaObject, destruct, [&](QMetaType, auto callback) { + return callback(sourceMetaType, source); + })) { return true; + } warn(); } } |