summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorThiago Macieira <thiago.macieira@intel.com>2022-01-17 09:38:22 -0800
committerThiago Macieira <thiago.macieira@intel.com>2022-01-18 03:56:40 +0000
commita59e7361714d50687d82a2d9abae9e95825a23b6 (patch)
tree0bf9d422eea1f40009665aceebfc0c27b693fc7c
parent9ab44777d6818a50cb02d745ff3eaf6b07adb394 (diff)
QMetaType: add a missing check for null d_ptr
Bug introduced in 6.0. This is the only unprotected d_ptr I could find. [ChangeLog][QtCore][QMetaType] Fixed a bug that would cause QMetaType::compare() and QVariant::compare() to crash on invalid meta types and variants. Pick-to: 6.2 6.3 Fixes: QTBUG-99960 Change-Id: I0e5f6bec596a4a78bd3bfffd16cb1f7b2d146688 Reviewed-by: Fabian Kosmale <fabian.kosmale@qt.io>
-rw-r--r--src/corelib/kernel/qmetatype.cpp2
-rw-r--r--tests/auto/corelib/kernel/qmetatype/tst_qmetatype.cpp53
-rw-r--r--tests/auto/corelib/kernel/qmetatype/tst_qmetatype.h2
3 files changed, 56 insertions, 1 deletions
diff --git a/src/corelib/kernel/qmetatype.cpp b/src/corelib/kernel/qmetatype.cpp
index 4828ba0764..59b1f23d21 100644
--- a/src/corelib/kernel/qmetatype.cpp
+++ b/src/corelib/kernel/qmetatype.cpp
@@ -750,7 +750,7 @@ QPartialOrdering QMetaType::compare(const void *lhs, const void *rhs) const
{
if (!lhs || !rhs)
return QPartialOrdering::Unordered;
- if (d_ptr->flags & QMetaType::IsPointer)
+ if (d_ptr && d_ptr->flags & QMetaType::IsPointer)
return threeWayCompare(*reinterpret_cast<const void * const *>(lhs),
*reinterpret_cast<const void * const *>(rhs));
if (d_ptr && d_ptr->lessThan) {
diff --git a/tests/auto/corelib/kernel/qmetatype/tst_qmetatype.cpp b/tests/auto/corelib/kernel/qmetatype/tst_qmetatype.cpp
index 740dcbc9be..96c8e2a559 100644
--- a/tests/auto/corelib/kernel/qmetatype/tst_qmetatype.cpp
+++ b/tests/auto/corelib/kernel/qmetatype/tst_qmetatype.cpp
@@ -39,6 +39,7 @@
#include <vector>
Q_DECLARE_METATYPE(QMetaType::Type)
+Q_DECLARE_METATYPE(QPartialOrdering)
namespace CheckTypeTraits
{
@@ -1346,6 +1347,58 @@ FOR_EACH_CORE_METATYPE(RETURN_CONSTRUCT_COPY_FUNCTION)
TypeTestFunctionGetter::get(type)();
}
+void tst_QMetaType::selfCompare_data()
+{
+ qRegisterMetaType<QPartialOrdering>();
+ QTest::addColumn<int>("type");
+ QTest::addColumn<QPartialOrdering>("order");
+
+ auto orderingFor = [](QMetaType::Type t) {
+ if (t == QMetaType::UnknownType || t == QMetaType::Void)
+ return QPartialOrdering::Unordered;
+ return QPartialOrdering::Equivalent;
+ };
+
+ QTest::newRow("unknown-type") << int(QMetaType::UnknownType) << orderingFor(QMetaType::UnknownType);
+
+#define ADD_METATYPE_TEST_ROW(MetaTypeName, MetaTypeId, RealType) \
+ QTest::newRow(QMetaType::typeName(QMetaType::MetaTypeName)) << int(QMetaType::MetaTypeName) << orderingFor(QMetaType::MetaTypeName);
+FOR_EACH_CORE_METATYPE(ADD_METATYPE_TEST_ROW)
+#undef ADD_METATYPE_TEST_ROW
+}
+
+void tst_QMetaType::selfCompare()
+{
+ QFETCH(int, type);
+ QFETCH(QPartialOrdering, order);
+
+ QMetaType t(type);
+ void *v1 = t.create(nullptr);
+ void *v2 = t.create(nullptr);
+ auto scope = qScopeGuard([=] {
+ t.destroy(v1);
+ t.destroy(v2);
+ });
+
+ // all these types have an equality comparator
+ QCOMPARE(t.equals(v1, v2), order == QPartialOrdering::Equivalent);
+
+ if (t.iface() && t.iface()->lessThan)
+ QCOMPARE(t.compare(v1, v2), order);
+
+ // for the primitive types, do a memcmp() too
+ switch (type) {
+ default:
+ break;
+
+#define ADD_METATYPE_CASE(MetaTypeName, MetaTypeId, RealType) \
+ case QMetaType::MetaTypeName:
+FOR_EACH_PRIMITIVE_METATYPE(ADD_METATYPE_CASE)
+#undef ADD_METATYPE_CASE
+ QCOMPARE(memcmp(v1, v2, t.sizeOf()), 0);
+ }
+}
+
typedef QString CustomString;
Q_DECLARE_METATYPE(CustomString) //this line is useless
diff --git a/tests/auto/corelib/kernel/qmetatype/tst_qmetatype.h b/tests/auto/corelib/kernel/qmetatype/tst_qmetatype.h
index b126b86475..15fe3e6874 100644
--- a/tests/auto/corelib/kernel/qmetatype/tst_qmetatype.h
+++ b/tests/auto/corelib/kernel/qmetatype/tst_qmetatype.h
@@ -104,6 +104,8 @@ private slots:
void typedConstruct();
void constructCopy_data();
void constructCopy();
+ void selfCompare_data();
+ void selfCompare();
void typedefs();
void registerType();
void isRegistered_data();