aboutsummaryrefslogtreecommitdiffstats
path: root/src/qml/qml
diff options
context:
space:
mode:
authorAndrei Golubev <andrei.golubev@qt.io>2022-05-02 14:24:55 +0200
committerAndrei Golubev <andrei.golubev@qt.io>2022-05-04 22:34:15 +0200
commit218eb5f5712dd920459cb0108fcd305d653352bc (patch)
tree34798f00d69bb5458b62813a7808400d9fbb0115 /src/qml/qml
parent57f025ee83728ae5debb9e71649e2bd80614f39f (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 Change-Id: I63c6e535d4df5169e0279eb2f588593f43a70640 Reviewed-by: Ulf Hermann <ulf.hermann@qt.io>
Diffstat (limited to 'src/qml/qml')
-rw-r--r--src/qml/qml/qqmlmetatype.cpp57
-rw-r--r--src/qml/qml/qqmlmetatype_p.h7
-rw-r--r--src/qml/qml/qqmlproxymetaobject.cpp9
-rw-r--r--src/qml/qml/qqmltype.cpp9
4 files changed, 44 insertions, 38 deletions
diff --git a/src/qml/qml/qqmlmetatype.cpp b/src/qml/qml/qqmlmetatype.cpp
index 7b14c5b468..8d4df5d85e 100644
--- a/src/qml/qml/qqmlmetatype.cpp
+++ b/src/qml/qml/qqmlmetatype.cpp
@@ -236,7 +236,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());
@@ -253,40 +254,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);
+ }
}
}
@@ -1640,7 +1642,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);
QMetaObject *mmo = builder.toMetaObject();
mmo->d.superdata = baseMetaObject;
if (!metaObjects.isEmpty())
diff --git a/src/qml/qml/qqmlmetatype_p.h b/src/qml/qml/qqmlmetatype_p.h
index 31ceb8d7f8..2c010f516d 100644
--- a/src/qml/qml/qqmlmetatype_p.h
+++ b/src/qml/qml/qqmlmetatype_p.h
@@ -258,8 +258,13 @@ public:
const QMetaObject *baseMetaObject,
QMetaObject *lastMetaObject);
+ enum ClonePolicy {
+ CloneAll, // default
+ CloneEnumsOnly, // skip properties and methods
+ };
static void clone(QMetaObjectBuilder &builder, const QMetaObject *mo,
- const QMetaObject *ignoreStart, const QMetaObject *ignoreEnd);
+ const QMetaObject *ignoreStart, const QMetaObject *ignoreEnd,
+ ClonePolicy policy);
static void qmlInsertModuleRegistration(const QString &uri, void (*registerFunction)());
static void qmlRemoveModuleRegistration(const QString &uri);
diff --git a/src/qml/qml/qqmlproxymetaobject.cpp b/src/qml/qml/qqmlproxymetaobject.cpp
index 53db6e71af..e05c63794c 100644
--- a/src/qml/qml/qqmlproxymetaobject.cpp
+++ b/src/qml/qml/qqmlproxymetaobject.cpp
@@ -68,11 +68,8 @@ QQmlProxyMetaObject::~QQmlProxyMetaObject()
QObject *QQmlProxyMetaObject::getProxy(int index)
{
if (!proxies) {
- if (!proxies) {
- proxies = new QObject*[metaObjects->count()];
- ::memset(proxies, 0,
- sizeof(QObject *) * metaObjects->count());
- }
+ proxies = new QObject *[metaObjects->count()];
+ ::memset(proxies, 0, sizeof(QObject *) * metaObjects->count());
}
if (!proxies[index]) {
@@ -116,6 +113,7 @@ int QQmlProxyMetaObject::metaCall(QObject *o, QMetaObject::Call c, int id, void
continue;
QObject *proxy = getProxy(ii);
+ Q_ASSERT(proxy);
const int localProxyOffset = proxy->metaObject()->propertyOffset();
const int localProxyId = id - globalPropertyOffset + localProxyOffset;
return proxy->qt_metacall(c, localProxyId, a);
@@ -138,6 +136,7 @@ int QQmlProxyMetaObject::metaCall(QObject *o, QMetaObject::Call c, int id, void
continue;
QObject *proxy = getProxy(ii);
+ Q_ASSERT(proxy);
const int localMethodOffset = proxy->metaObject()->methodOffset();
const int localMethodId = id - globalMethodOffset + localMethodOffset;
return proxy->qt_metacall(c, localMethodId, a);
diff --git a/src/qml/qml/qqmltype.cpp b/src/qml/qml/qqmltype.cpp
index d4c16e8e05..1d34b57fed 100644
--- a/src/qml/qml/qqmltype.cpp
+++ b/src/qml/qml/qqmltype.cpp
@@ -219,16 +219,15 @@ void QQmlTypePrivate::init() const
return;
}
- auto setupExtendedMetaObject = [&](
- const QMetaObject *extMetaObject,
- QObject *(*extFunc)(QObject *)) {
-
+ auto setupExtendedMetaObject = [&](const QMetaObject *extMetaObject,
+ QObject *(*extFunc)(QObject *)) {
if (!extMetaObject)
return;
// XXX - very inefficient
QMetaObjectBuilder builder;
- QQmlMetaType::clone(builder, extMetaObject, extMetaObject, extMetaObject);
+ QQmlMetaType::clone(builder, extMetaObject, extMetaObject, extMetaObject,
+ extFunc ? QQmlMetaType::CloneAll : QQmlMetaType::CloneEnumsOnly);
QMetaObject *mmo = builder.toMetaObject();
mmo->d.superdata = mo;
QQmlProxyMetaObject::ProxyData data = { mmo, extFunc, 0, 0 };