From d1a8623ecb4ef9f9942873503af7eb21a420ec7e Mon Sep 17 00:00:00 2001 From: Stephen Kelly Date: Thu, 5 Sep 2013 11:00:25 +0200 Subject: [PATCH] QVariant: Don't crash when doing user-defined conversion to QObject* The destructor of the ConverterFunctor calls unregisterConverter. If the instance is static (as it is in qmetatype.h), then this method can be called after the QGlobalStatic has already been destroyed. Change-Id: I33b70734cbe09dfa888e887280c349e43ad1b855 Reviewed-by: Olivier Goffart --- src/corelib/kernel/qmetatype.cpp | 2 ++ .../corelib/kernel/qvariant/tst_qvariant.cpp | 36 +++++++++++++++++++ 2 files changed, 38 insertions(+) diff --git a/src/corelib/kernel/qmetatype.cpp b/src/corelib/kernel/qmetatype.cpp index 586d6cf29f..17fbbda720 100644 --- a/src/corelib/kernel/qmetatype.cpp +++ b/src/corelib/kernel/qmetatype.cpp @@ -558,6 +558,8 @@ bool QMetaType::registerConverterFunction(const QtPrivate::AbstractConverterFunc */ void QMetaType::unregisterConverterFunction(int from, int to) { + if (customTypesConversionRegistry.isDestroyed()) + return; customTypesConversionRegistry()->remove(from, to); } diff --git a/tests/auto/corelib/kernel/qvariant/tst_qvariant.cpp b/tests/auto/corelib/kernel/qvariant/tst_qvariant.cpp index dab40db0ec..39b16200df 100644 --- a/tests/auto/corelib/kernel/qvariant/tst_qvariant.cpp +++ b/tests/auto/corelib/kernel/qvariant/tst_qvariant.cpp @@ -154,6 +154,7 @@ private slots: void qvariant_cast_QObject_data(); void qvariant_cast_QObject(); void qvariant_cast_QObject_derived(); + void qvariant_cast_QObject_wrapper(); void toLocale(); @@ -2235,6 +2236,41 @@ void tst_QVariant::qvariant_cast_QObject_derived() } } +struct QObjectWrapper +{ + explicit QObjectWrapper(QObject *o = 0) : obj(o) {} + + QObject* getObject() const { + return obj; + } +private: + QObject *obj; +}; + +Q_DECLARE_METATYPE(QObjectWrapper) + +struct Converter +{ + Converter() {} + + QObject* operator()(const QObjectWrapper &f) const + { + return f.getObject(); + } +}; + +void tst_QVariant::qvariant_cast_QObject_wrapper() +{ + QMetaType::registerConverter(&QObjectWrapper::getObject); + + CustomQObjectDerived *object = new CustomQObjectDerived(this); + QObjectWrapper wrapper(object); + QVariant v = QVariant::fromValue(wrapper); + v.convert(qMetaTypeId()); + QCOMPARE(v.value(), object); + +} + void tst_QVariant::convertToQUint8() const { /* qint8. */