From 315443d767bd5bd48430dc0c4ef0040238d916e4 Mon Sep 17 00:00:00 2001 From: Ulf Hermann Date: Tue, 13 Jul 2021 11:48:46 +0200 Subject: QVariant: Tolerate QObject* metatypes without QMetaObject QMetaType does. QVariant should do the same. Change-Id: I3419276b78b3b5ce8bd144dee92685195797d568 Reviewed-by: Fabian Kosmale Reviewed-by: Daniel Nicoletti Reviewed-by: Lars Knoll (cherry picked from commit 6f8ef8c64d4e7af92f585d10a1d5815fcb67831b) Reviewed-by: Qt Cherry-pick Bot --- src/corelib/kernel/qvariant.cpp | 8 ++-- .../auto/corelib/kernel/qvariant/tst_qvariant.cpp | 48 ++++++++++++++++++++++ 2 files changed, 53 insertions(+), 3 deletions(-) diff --git a/src/corelib/kernel/qvariant.cpp b/src/corelib/kernel/qvariant.cpp index dcba73731c..8a1197dc5f 100644 --- a/src/corelib/kernel/qvariant.cpp +++ b/src/corelib/kernel/qvariant.cpp @@ -2341,9 +2341,11 @@ static bool numericEquals(const QVariant::Private *d1, const QVariant::Private * #ifndef QT_BOOTSTRAPPED static bool canConvertMetaObject(QMetaType fromType, QMetaType toType) { - if ((fromType.flags() & QMetaType::PointerToQObject) && (toType.flags() & QMetaType::PointerToQObject)) { - return fromType.metaObject()->inherits(toType.metaObject()) || - toType.metaObject()->inherits(fromType.metaObject()); + if ((fromType.flags() & QMetaType::PointerToQObject) + && (toType.flags() & QMetaType::PointerToQObject)) { + const QMetaObject *f = fromType.metaObject(); + const QMetaObject *t = toType.metaObject(); + return f && t && (f->inherits(t) || t->inherits(f)); } return false; } diff --git a/tests/auto/corelib/kernel/qvariant/tst_qvariant.cpp b/tests/auto/corelib/kernel/qvariant/tst_qvariant.cpp index 4e5eb430a2..c26f09441b 100644 --- a/tests/auto/corelib/kernel/qvariant/tst_qvariant.cpp +++ b/tests/auto/corelib/kernel/qvariant/tst_qvariant.cpp @@ -63,6 +63,7 @@ #include "qnumeric.h" #include +#include #include "tst_qvariant_common.h" #include @@ -309,6 +310,7 @@ private slots: void mutableView(); void moveOperations(); + void equalsWithoutMetaObject(); private: void dataStream_data(QDataStream::Version version); @@ -5084,5 +5086,51 @@ void tst_QVariant::moveOperations() QVERIFY(v2.value>() == list); } +class NoMetaObject : public QObject {}; +void tst_QVariant::equalsWithoutMetaObject() +{ + using T = NoMetaObject*; + QtPrivate::QMetaTypeInterface d = { + /*.revision=*/ 0, + /*.alignment=*/ alignof(T), + /*.size=*/ sizeof(T), + /*.flags=*/ QtPrivate::QMetaTypeTypeFlags::Flags, + /*.typeId=*/ 0, + /*.metaObject=*/ nullptr, // on purpose. + /*.name=*/ "NoMetaObject*", + /*.defaultCtr=*/ [](const QtPrivate::QMetaTypeInterface *, void *addr) { + new (addr) T(); + }, + /*.copyCtr=*/ [](const QtPrivate::QMetaTypeInterface *, void *addr, const void *other) { + new (addr) T(*reinterpret_cast(other)); + }, + /*.moveCtr=*/ [](const QtPrivate::QMetaTypeInterface *, void *addr, void *other) { + new (addr) T(std::move(*reinterpret_cast(other))); + }, + /*.dtor=*/ [](const QtPrivate::QMetaTypeInterface *, void *addr) { + reinterpret_cast(addr)->~T(); + }, + /*.equals*/ nullptr, + /*.lessThan*/ nullptr, + /*.debugStream=*/ nullptr, + /*.dataStreamOut=*/ nullptr, + /*.dataStreamIn=*/ nullptr, + /*.legacyRegisterOp=*/ nullptr + }; + + QMetaType noMetaObjectMetaType(&d); + QMetaType qobjectMetaType = QMetaType::fromType(); + + QVERIFY(noMetaObjectMetaType.flags() & QMetaType::PointerToQObject); + QVERIFY(qobjectMetaType.flags() & QMetaType::PointerToQObject); + + QVariant noMetaObjectVariant(noMetaObjectMetaType, nullptr); + QVariant qobjectVariant(qobjectMetaType, nullptr); + + // Shouldn't crash + QVERIFY(noMetaObjectVariant != qobjectVariant); + QVERIFY(qobjectVariant != noMetaObjectVariant); +} + QTEST_MAIN(tst_QVariant) #include "tst_qvariant.moc" -- cgit v1.2.3