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>
This commit is contained in:
parent
3ae1eb6236
commit
a3a7d485fa
@ -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;
|
||||
}
|
||||
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -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"
|
||||
|
Loading…
Reference in New Issue
Block a user