summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorOlivier Goffart <ogoffart@woboq.com>2015-09-30 23:27:20 +0200
committerOlivier Goffart (Woboq GmbH) <ogoffart@woboq.com>2015-10-09 07:59:07 +0000
commita3a7d485fa2d572225c7050badf28784316aec37 (patch)
treebed8d082029123d2470bcbb2137d692786cd29a2
parent3ae1eb623685375468afb8cc71075467d54f12f3 (diff)
Fix crash in QMetaProperty::write for custom types and conversion
if t >= QMetaType::User, we would not return false nor call convert. We would then pass a pointer to whatever is in the QVariant to the qt_metacall that is expecting a pointer to an object of a different type. Since we have custom converters, we can call QVarent::convert even for custom types anyway. [ChangeLog][QtCore] Fixed crash when setting a QVariant of a different type to a property of a custom type. Attempt to do a conversion instead. Task-number: QTBUG-40644 Change-Id: Ib6fbd7e7ddcf25c5ee247ea04177e079f6d7de35 Reviewed-by: Jędrzej Nowacki <jedrzej.nowacki@theqtcompany.com>
-rw-r--r--src/corelib/kernel/qmetaobject.cpp4
-rw-r--r--src/dbus/qdbusinternalfilters.cpp3
-rw-r--r--tests/auto/corelib/kernel/qmetaproperty/tst_qmetaproperty.cpp45
3 files changed, 49 insertions, 3 deletions
diff --git a/src/corelib/kernel/qmetaobject.cpp b/src/corelib/kernel/qmetaobject.cpp
index f1ad74efb4..6abec27684 100644
--- a/src/corelib/kernel/qmetaobject.cpp
+++ b/src/corelib/kernel/qmetaobject.cpp
@@ -1,7 +1,7 @@
/****************************************************************************
**
** Copyright (C) 2015 The Qt Company Ltd.
-** Copyright (C) 2014 Olivier Goffart <ogoffart@woboq.com>
+** Copyright (C) 2015 Olivier Goffart <ogoffart@woboq.com>
** Contact: http://www.qt.io/licensing/
**
** This file is part of the QtCore module of the Qt Toolkit.
@@ -3068,7 +3068,7 @@ bool QMetaProperty::write(QObject *object, const QVariant &value) const
if (t == QMetaType::UnknownType)
return false;
}
- if (t != QMetaType::QVariant && t != (uint)value.userType() && (t < QMetaType::User && !v.convert((QVariant::Type)t)))
+ if (t != QMetaType::QVariant && int(t) != value.userType() && !v.convert(t))
return false;
}
diff --git a/src/dbus/qdbusinternalfilters.cpp b/src/dbus/qdbusinternalfilters.cpp
index d9e5f7408b..fd6f91e65a 100644
--- a/src/dbus/qdbusinternalfilters.cpp
+++ b/src/dbus/qdbusinternalfilters.cpp
@@ -366,6 +366,9 @@ static int writeProperty(QObject *obj, const QByteArray &property_name, QVariant
value = other;
}
+ if (mp.userType() == qMetaTypeId<QDBusVariant>())
+ value = QVariant::fromValue(QDBusVariant(value));
+
// the property type here should match
return mp.write(obj, value) ? PropertyWriteSuccess : PropertyWriteFailed;
}
diff --git a/tests/auto/corelib/kernel/qmetaproperty/tst_qmetaproperty.cpp b/tests/auto/corelib/kernel/qmetaproperty/tst_qmetaproperty.cpp
index 4d54aa4dc8..10656a0dcd 100644
--- a/tests/auto/corelib/kernel/qmetaproperty/tst_qmetaproperty.cpp
+++ b/tests/auto/corelib/kernel/qmetaproperty/tst_qmetaproperty.cpp
@@ -1,7 +1,7 @@
/****************************************************************************
**
** Copyright (C) 2015 The Qt Company Ltd.
-** Copyright (C) 2014 Olivier Goffart <ogoffart@woboq.com>
+** Copyright (C) 2015 Olivier Goffart <ogoffart@woboq.com>
** Contact: http://www.qt.io/licensing/
**
** This file is part of the test suite of the Qt Toolkit.
@@ -38,15 +38,29 @@
#include <qobject.h>
#include <qmetaobject.h>
+struct CustomType
+{
+ int padding;
+ QString str;
+ CustomType(const QString &str = QString()) : str(str) {}
+ operator QString() const { return str; }
+ friend bool operator!=(const CustomType &a, const CustomType &b)
+ { return a.str != b.str; }
+};
+
+Q_DECLARE_METATYPE(CustomType)
+
class tst_QMetaProperty : public QObject
{
Q_OBJECT
Q_PROPERTY(EnumType value WRITE setValue READ getValue)
Q_PROPERTY(EnumType value2 WRITE set_value READ get_value)
+ Q_PROPERTY(QString value7 MEMBER value7)
Q_PROPERTY(int value8 READ value8)
Q_PROPERTY(int value9 READ value9 CONSTANT)
Q_PROPERTY(int value10 READ value10 FINAL)
Q_PROPERTY(QMap<int, int> map MEMBER map)
+ Q_PROPERTY(CustomType custom MEMBER custom)
private slots:
void hasStdCppSet();
@@ -55,6 +69,7 @@ private slots:
void gadget();
void readAndWriteWithLazyRegistration();
void mapProperty();
+ void conversion();
public:
enum EnumType { EnumType1 };
@@ -68,7 +83,9 @@ public:
int value9() const { return 1; }
int value10() const { return 1; }
+ QString value7;
QMap<int, int> map;
+ CustomType custom;
};
void tst_QMetaProperty::hasStdCppSet()
@@ -195,5 +212,31 @@ void tst_QMetaProperty::mapProperty()
QCOMPARE(map, (v.value<QMap<int,int> >()));
}
+void tst_QMetaProperty::conversion()
+{
+ QMetaType::registerConverter<QString, CustomType>();
+ QMetaType::registerConverter<CustomType, QString>();
+
+ QString hello = QStringLiteral("Hello");
+
+ // Write to a QString property using a CustomType in a QVariant
+ QMetaProperty value7P = metaObject()->property(metaObject()->indexOfProperty("value7"));
+ QVERIFY(value7P.isValid());
+ QVERIFY(value7P.write(this, QVariant::fromValue(CustomType(hello))));
+ QCOMPARE(value7, hello);
+
+ // Write to a CustomType property using a QString in a QVariant
+ QMetaProperty customP = metaObject()->property(metaObject()->indexOfProperty("custom"));
+ QVERIFY(customP.isValid());
+ QVERIFY(customP.write(this, hello));
+ QCOMPARE(custom.str, hello);
+
+ // Something that cannot be converted should fail
+ QVERIFY(!customP.write(this, 45));
+ QVERIFY(!customP.write(this, QVariant::fromValue(this)));
+ QVERIFY(!value7P.write(this, QVariant::fromValue(this)));
+ QVERIFY(!value7P.write(this, QVariant::fromValue<QObject*>(this)));
+}
+
QTEST_MAIN(tst_QMetaProperty)
#include "tst_qmetaproperty.moc"