diff options
| author | Michael Brasser <mbrasser@ford.com> | 2019-10-07 10:37:37 -0500 |
|---|---|---|
| committer | Brett Stottlemyer <bstottle@ford.com> | 2021-07-22 08:57:19 -0400 |
| commit | 28093b4ac318209f12189efda9094797226eead1 (patch) | |
| tree | 212a31372920a0ac0bcd267b608359a108d41114 /src/remoteobjects/qremoteobjectsource.cpp | |
| parent | b6730532817d9b1bc296b90ca94dbe3fdca674d4 (diff) | |
Fix crash when remoting QML objects with sub-objects
There are two edge cases to watch out for. First, the property metaType's
metaObject() returns a nullptr, so the property QObject pointer's
metaObject needs to be used instead. If the QObject is null, the property
is skipped, as there is no way to get the metaobject without introducing
a dependency on QtQuick.
Pick-to: 6.2 5.15
Change-Id: I60ae36dffb30c840858e4d67b9980299c58354b4
Reviewed-by: Michael Brasser <michael.brasser@live.com>
Reviewed-by: Fabian Kosmale <fabian.kosmale@qt.io>
Diffstat (limited to 'src/remoteobjects/qremoteobjectsource.cpp')
| -rw-r--r-- | src/remoteobjects/qremoteobjectsource.cpp | 33 |
1 files changed, 24 insertions, 9 deletions
diff --git a/src/remoteobjects/qremoteobjectsource.cpp b/src/remoteobjects/qremoteobjectsource.cpp index e84cf64..61e4c17 100644 --- a/src/remoteobjects/qremoteobjectsource.cpp +++ b/src/remoteobjects/qremoteobjectsource.cpp @@ -112,7 +112,10 @@ QRemoteObjectSourceBase::QRemoteObjectSourceBase(QObject *obj, Private *d, const if (metaType.flags().testFlag(QMetaType::PointerToQObject)) { auto propertyMeta = metaType.metaObject(); QObject *child = property.read(m_object).value<QObject *>(); - if (propertyMeta->inherits(&QAbstractItemModel::staticMetaObject)) { + const QMetaObject *meta = child ? child->metaObject() : propertyMeta; + if (!meta) + continue; + if (meta->inherits(&QAbstractItemModel::staticMetaObject)) { const auto modelInfo = api->m_models.at(modelIndex++); QAbstractItemModel *model = qobject_cast<QAbstractItemModel *>(child); QAbstractItemAdapterSourceAPI<QAbstractItemModel, QAbstractItemModelSourceAdapter> *modelApi = @@ -452,14 +455,21 @@ DynamicApiMap::DynamicApiMap(QObject *object, const QMetaObject *metaObject, con const int propCount = metaObject->propertyCount(); const int propOffset = metaObject->propertyOffset(); m_properties.reserve(propCount-propOffset); - int i = 0; - for (i = propOffset; i < propCount; ++i) { + QSet<int> invalidSignals; + for (int i = propOffset; i < propCount; ++i) { const QMetaProperty property = metaObject->property(i); const auto metaType = property.metaType(); if (metaType.flags().testFlag(QMetaType::PointerToQObject)) { auto propertyMeta = metaType.metaObject(); QObject *child = property.read(object).value<QObject *>(); - if (propertyMeta->inherits(&QAbstractItemModel::staticMetaObject)) { + const QMetaObject *meta = child ? child->metaObject() : propertyMeta; + if (!meta) { + const int notifyIndex = metaObject->property(i).notifySignalIndex(); + if (notifyIndex != -1) + invalidSignals << notifyIndex; + continue; + } + if (meta->inherits(&QAbstractItemModel::staticMetaObject)) { const QByteArray name = QByteArray::fromRawData(property.name(), qsizetype(qstrlen(property.name()))); const QByteArray infoName = name.toUpper() + QByteArrayLiteral("_ROLES"); @@ -473,12 +483,15 @@ DynamicApiMap::DynamicApiMap(QObject *object, const QMetaObject *metaObject, con QString::fromLatin1(property.name()), roleInfo}); } else { - const QMetaObject *meta = child ? child->metaObject() : propertyMeta; QString typeName = QtRemoteObjects::getTypeNameAndMetaobjectFromClassInfo(meta); if (typeName.isNull()) { - typeName = QString::fromLatin1(propertyMeta->className()); + typeName = QString::fromLatin1(meta->className()); + if (typeName.contains(QLatin1String("QQuick"))) + typeName.remove(QLatin1String("QQuick")); + else if (int index = typeName.indexOf(QLatin1String("_QMLTYPE_"))) + typeName.truncate(index); // TODO better way to ensure we have consistent typenames between source/replicas? - if (typeName.endsWith(QLatin1String("Source"))) + else if (typeName.endsWith(QLatin1String("Source"))) typeName.chop(6); } @@ -497,11 +510,13 @@ DynamicApiMap::DynamicApiMap(QObject *object, const QMetaObject *metaObject, con } const int methodCount = metaObject->methodCount(); const int methodOffset = metaObject->methodOffset(); - for (i = methodOffset; i < methodCount; ++i) { + for (int i = methodOffset; i < methodCount; ++i) { const QMetaMethod mm = metaObject->method(i); const QMetaMethod::MethodType m = mm.methodType(); if (m == QMetaMethod::Signal) { - if (m_signals.indexOf(i) >= 0) //Already added as a property notifier + if (m_signals.indexOf(i) >= 0) // Already added as a property notifier + continue; + if (invalidSignals.contains(i)) // QObject with no metatype continue; m_signals << i; } else if (m == QMetaMethod::Slot || m == QMetaMethod::Method) |
