diff options
author | Andrei Golubev <andrei.golubev@qt.io> | 2022-05-02 14:24:55 +0200 |
---|---|---|
committer | Ulf Hermann <ulf.hermann@qt.io> | 2022-07-22 10:42:56 +0200 |
commit | 1c8d34e45947ff2a629335ee3f5acf29a57877fc (patch) | |
tree | 0bdeb33be4e347742b9d42540b9a6d9493c4e70d /src/qml/qml/qqmlmetatype.cpp | |
parent | be930b7a20461b0096212aa10559e400fb97affc (diff) |
QQmlProxyMetaObject: Ignore properties/methods of non-creatable proxies
Qt/QML allows marking a type with QML_EXTENDED_NAMESPACE(Type) where
Type is a Q_OBJECT. In this case, we have a Type-specific meta
object but do not have an extension function to create the object of
that Type with, causing us a subtle runtime crash. The crash in fact
happens when we attempt to access a shadowed property through the
extension object (which surely fails since there's no extension object)
Fix this by excluding properties and methods when cloning the metaobject
for the proxy if we know that the proxy cannot be created. This somewhat
matches what the documentation says about QML_EXTENDED_NAMESPACE:
When we have a Q_OBJECT/Q_GADGET, methods and properties of that are not
exposed
As a drive by, add the same check to the QQmlMetaType::proxyData().
While untested, this seems logical since the proxy data assumes valid
creation function in this case as well
Fixes: QTBUG-103081
Fixes: QTBUG-104700
Change-Id: I63c6e535d4df5169e0279eb2f588593f43a70640
Reviewed-by: Ulf Hermann <ulf.hermann@qt.io>
(cherry picked from commit 218eb5f5712dd920459cb0108fcd305d653352bc)
Reviewed-by: Qt CI Bot <qt_ci_bot@qt-project.org>
Reviewed-by: Fabian Kosmale <fabian.kosmale@qt.io>
Diffstat (limited to 'src/qml/qml/qqmlmetatype.cpp')
-rw-r--r-- | src/qml/qml/qqmlmetatype.cpp | 57 |
1 files changed, 30 insertions, 27 deletions
diff --git a/src/qml/qml/qqmlmetatype.cpp b/src/qml/qml/qqmlmetatype.cpp index a82363afbc..a4ed418548 100644 --- a/src/qml/qml/qqmlmetatype.cpp +++ b/src/qml/qml/qqmlmetatype.cpp @@ -226,7 +226,8 @@ static QQmlTypePrivate *createQQmlType(QQmlMetaTypeData *data, const QString &el } void QQmlMetaType::clone(QMetaObjectBuilder &builder, const QMetaObject *mo, - const QMetaObject *ignoreStart, const QMetaObject *ignoreEnd) + const QMetaObject *ignoreStart, const QMetaObject *ignoreEnd, + QQmlMetaType::ClonePolicy policy) { // Set classname builder.setClassName(ignoreEnd->className()); @@ -243,40 +244,41 @@ void QQmlMetaType::clone(QMetaObjectBuilder &builder, const QMetaObject *mo, } } - // Clone Q_METHODS - do this first to avoid duplicating the notify signals. - for (int ii = mo->methodOffset(); ii < mo->methodCount(); ++ii) { - QMetaMethod method = mo->method(ii); + if (policy != QQmlMetaType::CloneEnumsOnly) { + // Clone Q_METHODS - do this first to avoid duplicating the notify signals. + for (int ii = mo->methodOffset(); ii < mo->methodCount(); ++ii) { + QMetaMethod method = mo->method(ii); - // More complex - need to search name - QByteArray name = method.name(); + // More complex - need to search name + QByteArray name = method.name(); + bool found = false; - bool found = false; + for (int ii = ignoreStart->methodOffset() + ignoreStart->methodCount(); + !found && ii < ignoreEnd->methodOffset() + ignoreEnd->methodCount(); ++ii) { - for (int ii = ignoreStart->methodOffset() + ignoreStart->methodCount(); - !found && ii < ignoreEnd->methodOffset() + ignoreEnd->methodCount(); - ++ii) { + QMetaMethod other = ignoreEnd->method(ii); - QMetaMethod other = ignoreEnd->method(ii); + found = name == other.name(); + } - found = name == other.name(); + QMetaMethodBuilder m = builder.addMethod(method); + if (found) // SKIP + m.setAccess(QMetaMethod::Private); } - QMetaMethodBuilder m = builder.addMethod(method); - if (found) // SKIP - m.setAccess(QMetaMethod::Private); - } - - // Clone Q_PROPERTY - for (int ii = mo->propertyOffset(); ii < mo->propertyCount(); ++ii) { - QMetaProperty property = mo->property(ii); + // Clone Q_PROPERTY + for (int ii = mo->propertyOffset(); ii < mo->propertyCount(); ++ii) { + QMetaProperty property = mo->property(ii); - int otherIndex = ignoreEnd->indexOfProperty(property.name()); - if (otherIndex >= ignoreStart->propertyOffset() + ignoreStart->propertyCount()) { - builder.addProperty(QByteArray("__qml_ignore__") + property.name(), QByteArray("void")); - // Skip - } else { - builder.addProperty(property); + int otherIndex = ignoreEnd->indexOfProperty(property.name()); + if (otherIndex >= ignoreStart->propertyOffset() + ignoreStart->propertyCount()) { + builder.addProperty(QByteArray("__qml_ignore__") + property.name(), + QByteArray("void")); + // Skip + } else { + builder.addProperty(property); + } } } @@ -1521,7 +1523,8 @@ QList<QQmlProxyMetaObject::ProxyData> QQmlMetaType::proxyData(const QMetaObject return; QMetaObjectBuilder builder; - clone(builder, extMetaObject, superdataBaseMetaObject, baseMetaObject); + clone(builder, extMetaObject, superdataBaseMetaObject, baseMetaObject, + extFunc ? QQmlMetaType::CloneAll : QQmlMetaType::CloneEnumsOnly); builder.setFlags(MetaObjectFlag::DynamicMetaObject); QMetaObject *mmo = builder.toMetaObject(); mmo->d.superdata = baseMetaObject; |