diff options
author | Volker Krause <volker.krause@kdab.com> | 2012-07-27 10:59:47 +0200 |
---|---|---|
committer | Qt by Nokia <qt-info@nokia.com> | 2012-07-27 12:23:43 +0200 |
commit | ef403ba46a0fc28f9209d66de153e4a44ab635ff (patch) | |
tree | d87aac50cfbe034511c2a28c3029fcbfadce2dfb | |
parent | ddaee978d1f1b21053eeb060ccc0ad9e49fa93ba (diff) |
Fix crash in QVariant::canConvert().
When containing a QObject (or sub-class) pointer and trying to convert
to a QObject pointer canConvert() did dereference the pointer without
checking for it being null.
Change-Id: Ie274e54f2f817f2b6c5df64504f8af6359b8f38d
Reviewed-by: Stephen Kelly <stephen.kelly@kdab.com>
-rw-r--r-- | src/corelib/kernel/qvariant.cpp | 5 | ||||
-rw-r--r-- | tests/auto/corelib/kernel/qvariant/tst_qvariant.cpp | 28 |
2 files changed, 22 insertions, 11 deletions
diff --git a/src/corelib/kernel/qvariant.cpp b/src/corelib/kernel/qvariant.cpp index f8c7046c68..ff5a02b380 100644 --- a/src/corelib/kernel/qvariant.cpp +++ b/src/corelib/kernel/qvariant.cpp @@ -2553,8 +2553,11 @@ static bool canConvertMetaObject(int fromId, int toId, QObject *fromObject) { #ifndef QT_BOOTSTRAPPED QMetaType toType(toId); - if ((QMetaType::typeFlags(fromId) & QMetaType::PointerToQObject) && (toType.flags() & QMetaType::PointerToQObject)) + if ((QMetaType::typeFlags(fromId) & QMetaType::PointerToQObject) && (toType.flags() & QMetaType::PointerToQObject)) { + if (!fromObject) + return true; return canConvertMetaObject(fromObject->metaObject(), toType.metaObject()); + } #else Q_UNUSED(fromId); Q_UNUSED(toId); diff --git a/tests/auto/corelib/kernel/qvariant/tst_qvariant.cpp b/tests/auto/corelib/kernel/qvariant/tst_qvariant.cpp index 7fc092b44d..6e1b9f87a7 100644 --- a/tests/auto/corelib/kernel/qvariant/tst_qvariant.cpp +++ b/tests/auto/corelib/kernel/qvariant/tst_qvariant.cpp @@ -2100,39 +2100,47 @@ void tst_QVariant::qvariant_cast_QObject_data() { QTest::addColumn<QVariant>("data"); QTest::addColumn<bool>("success"); + QTest::addColumn<bool>("isNull"); QObject *obj = new QObject; obj->setObjectName(QString::fromLatin1("Hello")); - QTest::newRow("from QObject") << QVariant(QMetaType::QObjectStar, &obj) << true; - QTest::newRow("from QObject2") << QVariant::fromValue(obj) << true; - QTest::newRow("from String") << QVariant(QLatin1String("1, 2, 3")) << false; - QTest::newRow("from int") << QVariant((int) 123) << false; + QTest::newRow("from QObject") << QVariant(QMetaType::QObjectStar, &obj) << true << false; + QTest::newRow("from QObject2") << QVariant::fromValue(obj) << true << false; + QTest::newRow("from String") << QVariant(QLatin1String("1, 2, 3")) << false << false; + QTest::newRow("from int") << QVariant((int) 123) << false << false; CustomQObject *customObject = new CustomQObject(this); customObject->setObjectName(QString::fromLatin1("Hello")); - QTest::newRow("from Derived QObject") << QVariant::fromValue(customObject) << true; - QTest::newRow("from custom Object") << QVariant::fromValue(CustomNonQObject()) << false; + QTest::newRow("from Derived QObject") << QVariant::fromValue(customObject) << true << false; + QTest::newRow("from custom Object") << QVariant::fromValue(CustomNonQObject()) << false << false; // Deleted in cleanupTestCase. customNonQObjectPointer = new CustomNonQObject; - QTest::newRow("from custom ObjectStar") << QVariant::fromValue(customNonQObjectPointer) << false; + QTest::newRow("from custom ObjectStar") << QVariant::fromValue(customNonQObjectPointer) << false << false; // Deleted in cleanupTestCase. objectPointerTestData.push_back(obj); objectPointerTestData.push_back(customObject); + + QTest::newRow("null QObject") << QVariant::fromValue<QObject*>(0) << true << true; + QTest::newRow("null derived QObject") << QVariant::fromValue<CustomQObject*>(0) << true << true; + QTest::newRow("null custom object") << QVariant::fromValue<CustomNonQObject*>(0) << false << true; + QTest::newRow("null int") << QVariant::fromValue<int>(0) << false << true; } void tst_QVariant::qvariant_cast_QObject() { QFETCH(QVariant, data); QFETCH(bool, success); + QFETCH(bool, isNull); QObject *o = qvariant_cast<QObject *>(data); - QCOMPARE(o != 0, success); + QCOMPARE(o != 0, success && !isNull); if (success) { - QCOMPARE(o->objectName(), QString::fromLatin1("Hello")); + if (!isNull) + QCOMPARE(o->objectName(), QString::fromLatin1("Hello")); QVERIFY(data.canConvert<QObject*>()); QVERIFY(data.canConvert(QMetaType::QObjectStar)); QVERIFY(data.canConvert(::qMetaTypeId<QObject*>())); - QVERIFY(data.value<QObject*>()); + QCOMPARE(data.value<QObject*>() == 0, isNull); QVERIFY(data.convert(QMetaType::QObjectStar)); QCOMPARE(data.userType(), int(QMetaType::QObjectStar)); } else { |