diff options
author | Milian Wolff <milian.wolff@kdab.com> | 2017-08-07 23:24:57 +0200 |
---|---|---|
committer | Milian Wolff <milian.wolff@kdab.com> | 2017-08-08 20:55:01 +0000 |
commit | b5229df6a08a902b11a2fc9529af6385f4d985d5 (patch) | |
tree | 09c9b0ca5e16c317441ff62e2a5a5408ee64c423 | |
parent | 01bd2b3ca88b42b9daac7cb00d196eb90d168570 (diff) | |
download | qtwebchannel-b5229df6a08a902b11a2fc9529af6385f4d985d5.tar.gz |
Do not crash on non-QVariant return types
Patch e354bdc5 introduced a regression that triggers a crash
in Qt 5.9 when returning a type that is not implicitly convertible
to QVariant, such as a QJsonValue, from an invoked method/slot.
This patch fixes this situation and adds proper unit test coverage.
Change-Id: Ib8cb0c96e7496bc8dc9a628245d7a44e4234aff0
Task-number: QTBUG-62045
Reviewed-by: Frederik Gladhorn <frederik.gladhorn@qt.io>
Reviewed-by: Kai Dohmen <psykai1993@googlemail.com>
-rw-r--r-- | src/webchannel/qmetaobjectpublisher.cpp | 4 | ||||
-rw-r--r-- | tests/auto/webchannel/tst_webchannel.cpp | 34 | ||||
-rw-r--r-- | tests/auto/webchannel/tst_webchannel.h | 15 |
3 files changed, 41 insertions, 12 deletions
diff --git a/src/webchannel/qmetaobjectpublisher.cpp b/src/webchannel/qmetaobjectpublisher.cpp index dcc589c..cfc6ad2 100644 --- a/src/webchannel/qmetaobjectpublisher.cpp +++ b/src/webchannel/qmetaobjectpublisher.cpp @@ -383,12 +383,12 @@ QVariant QMetaObjectPublisher::invokeMethod(QObject *const object, const int met arguments[0], arguments[1], arguments[2], arguments[3], arguments[4], arguments[5], arguments[6], arguments[7], arguments[8], arguments[9]); } else { - QGenericReturnArgument returnArgument(method.typeName(), returnValue.data()); - // Only init variant with return type if its not a variant itself, which would // lead to nested variants which is not what we want. if (method.returnType() != QMetaType::QVariant) returnValue = QVariant(method.returnType(), 0); + + QGenericReturnArgument returnArgument(method.typeName(), returnValue.data()); method.invoke(object, returnArgument, arguments[0], arguments[1], arguments[2], arguments[3], arguments[4], arguments[5], arguments[6], arguments[7], arguments[8], arguments[9]); diff --git a/tests/auto/webchannel/tst_webchannel.cpp b/tests/auto/webchannel/tst_webchannel.cpp index 2e80477..f214b7e 100644 --- a/tests/auto/webchannel/tst_webchannel.cpp +++ b/tests/auto/webchannel/tst_webchannel.cpp @@ -536,6 +536,10 @@ void TestWebChannel::testInvokeMethodConversion() QVERIFY(method != -1); channel.d_func()->publisher->invokeMethod(this, method, args); QCOMPARE(m_lastInt, args.at(0).toInt()); + int getterMethod = metaObject()->indexOfMethod("readInt()"); + QVERIFY(getterMethod != -1); + auto retVal = channel.d_func()->publisher->invokeMethod(this, getterMethod, {}); + QCOMPARE(retVal, args.at(0).toVariant()); } { int method = metaObject()->indexOfMethod("setBool(bool)"); @@ -544,24 +548,40 @@ void TestWebChannel::testInvokeMethodConversion() args.append(QJsonValue(!m_lastBool)); channel.d_func()->publisher->invokeMethod(this, method, args); QCOMPARE(m_lastBool, args.at(0).toBool()); + int getterMethod = metaObject()->indexOfMethod("readBool()"); + QVERIFY(getterMethod != -1); + auto retVal = channel.d_func()->publisher->invokeMethod(this, getterMethod, {}); + QCOMPARE(retVal, args.at(0).toVariant()); } { int method = metaObject()->indexOfMethod("setDouble(double)"); QVERIFY(method != -1); channel.d_func()->publisher->invokeMethod(this, method, args); QCOMPARE(m_lastDouble, args.at(0).toDouble()); + int getterMethod = metaObject()->indexOfMethod("readDouble()"); + QVERIFY(getterMethod != -1); + auto retVal = channel.d_func()->publisher->invokeMethod(this, getterMethod, {}); + QCOMPARE(retVal, args.at(0).toVariant()); } { int method = metaObject()->indexOfMethod("setVariant(QVariant)"); QVERIFY(method != -1); channel.d_func()->publisher->invokeMethod(this, method, args); QCOMPARE(m_lastVariant, args.at(0).toVariant()); + int getterMethod = metaObject()->indexOfMethod("readVariant()"); + QVERIFY(getterMethod != -1); + auto retVal = channel.d_func()->publisher->invokeMethod(this, getterMethod, {}); + QCOMPARE(retVal, args.at(0).toVariant()); } { int method = metaObject()->indexOfMethod("setJsonValue(QJsonValue)"); QVERIFY(method != -1); channel.d_func()->publisher->invokeMethod(this, method, args); QCOMPARE(m_lastJsonValue, args.at(0)); + int getterMethod = metaObject()->indexOfMethod("readJsonValue()"); + QVERIFY(getterMethod != -1); + auto retVal = channel.d_func()->publisher->invokeMethod(this, getterMethod, {}); + QCOMPARE(retVal, args.at(0).toVariant()); } { int method = metaObject()->indexOfMethod("setJsonObject(QJsonObject)"); @@ -572,16 +592,24 @@ void TestWebChannel::testInvokeMethodConversion() args[0] = object; channel.d_func()->publisher->invokeMethod(this, method, args); QCOMPARE(m_lastJsonObject, object); + int getterMethod = metaObject()->indexOfMethod("readJsonObject()"); + QVERIFY(getterMethod != -1); + auto retVal = channel.d_func()->publisher->invokeMethod(this, getterMethod, {}); + QCOMPARE(retVal, QVariant::fromValue(object)); } { - int method = metaObject()->indexOfMethod("setJsonArray(QJsonArray)"); - QVERIFY(method != -1); + int setterMethod = metaObject()->indexOfMethod("setJsonArray(QJsonArray)"); + QVERIFY(setterMethod != -1); QJsonArray array; array << QJsonValue(123); array << QJsonValue(4.2); args[0] = array; - channel.d_func()->publisher->invokeMethod(this, method, args); + channel.d_func()->publisher->invokeMethod(this, setterMethod, args); QCOMPARE(m_lastJsonArray, array); + int getterMethod = metaObject()->indexOfMethod("readJsonArray()"); + QVERIFY(getterMethod != -1); + auto retVal = channel.d_func()->publisher->invokeMethod(this, getterMethod, {}); + QCOMPARE(retVal, QVariant::fromValue(array)); } } diff --git a/tests/auto/webchannel/tst_webchannel.h b/tests/auto/webchannel/tst_webchannel.h index aaacb5a..d2597e5 100644 --- a/tests/auto/webchannel/tst_webchannel.h +++ b/tests/auto/webchannel/tst_webchannel.h @@ -258,20 +258,21 @@ public: explicit TestWebChannel(QObject *parent = 0); virtual ~TestWebChannel(); +public slots: int readInt() const; - Q_INVOKABLE void setInt(int i); + void setInt(int i); bool readBool() const; - Q_INVOKABLE void setBool(bool b); + void setBool(bool b); double readDouble() const; - Q_INVOKABLE void setDouble(double d); + void setDouble(double d); QVariant readVariant() const; - Q_INVOKABLE void setVariant(const QVariant &v); + void setVariant(const QVariant &v); QJsonValue readJsonValue() const; - Q_INVOKABLE void setJsonValue(const QJsonValue &v); + void setJsonValue(const QJsonValue &v); QJsonObject readJsonObject() const; - Q_INVOKABLE void setJsonObject(const QJsonObject &v); + void setJsonObject(const QJsonObject &v); QJsonArray readJsonArray() const; - Q_INVOKABLE void setJsonArray(const QJsonArray &v); + void setJsonArray(const QJsonArray &v); signals: void lastIntChanged(); |