diff options
author | Ulf Hermann <[email protected]> | 2022-11-29 08:22:01 +0100 |
---|---|---|
committer | Ulf Hermann <[email protected]> | 2022-11-29 09:42:06 +0100 |
commit | 5595809245cfedeb86657277b8354f45ddda2528 (patch) | |
tree | b9565d428fd548bfc3c32eba7273d0c3304981de /src | |
parent | 6656567a4085e3d6de01226fb7b1ec16ee7ba08c (diff) |
QQmlNotifier: Guard against broken meta objects when disconnecting
Some classes may be unable to produce a metaObject via the string
casting method we employ when invalidating the interceptor metaObject.
Ignore those.
Furthermore, qt_metacast() may produce a different object than the one
we called it on. Accept that. Finally, we don't have to check the
topmost QMetaObject because we already know it's invalid.
Fixes: QTBUG-108906
Change-Id: Id935d06beead4239381093f2f090d4a6a244034b
Reviewed-by: Zoltan Gera <[email protected]>
Reviewed-by: Fabian Kosmale <[email protected]>
Diffstat (limited to 'src')
-rw-r--r-- | src/qml/qml/qqmlnotifier_p.h | 9 | ||||
-rw-r--r-- | src/qml/qml/qqmlvmemetaobject.cpp | 4 |
2 files changed, 8 insertions, 5 deletions
diff --git a/src/qml/qml/qqmlnotifier_p.h b/src/qml/qml/qqmlnotifier_p.h index 02f9017509..844766a633 100644 --- a/src/qml/qml/qqmlnotifier_p.h +++ b/src/qml/qml/qqmlnotifier_p.h @@ -172,12 +172,15 @@ void QQmlNotifierEndpoint::disconnect() if (next) next->prev = prev; if (prev) *prev = next; - if (sourceSignal != -1) { + if (sourceSignal != -1 && needsConnectNotify) { QObject * const obj = senderAsObject(); Q_ASSERT(obj); QObjectPrivate * const priv = QObjectPrivate::get(obj); - if (needsConnectNotify) - priv->disconnectNotify(QMetaObjectPrivate::signal(obj->metaObject(), sourceSignal)); + + // In some degenerate cases an object being destructed might be unable + // to produce a metaObject(). Therefore we check here. + if (const QMetaObject *mo = obj->metaObject()) + priv->disconnectNotify(QMetaObjectPrivate::signal(mo, sourceSignal)); } setSender(0x0); diff --git a/src/qml/qml/qqmlvmemetaobject.cpp b/src/qml/qml/qqmlvmemetaobject.cpp index 7ce1a48708..05b9328d99 100644 --- a/src/qml/qml/qqmlvmemetaobject.cpp +++ b/src/qml/qml/qqmlvmemetaobject.cpp @@ -349,7 +349,7 @@ bool QQmlInterceptorMetaObject::doIntercept(QMetaObject::Call c, int id, void ** static QMetaObject *stringCastMetaObject(QObject *o, const QMetaObject *top) { for (const QMetaObject *mo = top; mo; mo = mo->superClass()) { - if (o->qt_metacast(mo->className()) == o) + if (o->qt_metacast(mo->className()) != nullptr) return const_cast<QMetaObject *>(mo); } return nullptr; @@ -361,7 +361,7 @@ QMetaObject *QQmlInterceptorMetaObject::toDynamicMetaObject(QObject *o) metaObject = cache->createMetaObject(); if (Q_UNLIKELY(metaObject.tag() == MetaObjectInvalid)) - return stringCastMetaObject(o, metaObject.data()); + return stringCastMetaObject(o, metaObject->superClass()); // ### Qt7: The const_cast is only due to toDynamicMetaObject having the wrong return type. // It should be const QMetaObject *. Fix this. |