summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMilian Wolff <milian.wolff@kdab.com>2017-08-07 23:24:57 +0200
committerMilian Wolff <milian.wolff@kdab.com>2017-08-08 20:55:01 +0000
commitb5229df6a08a902b11a2fc9529af6385f4d985d5 (patch)
tree09c9b0ca5e16c317441ff62e2a5a5408ee64c423
parent01bd2b3ca88b42b9daac7cb00d196eb90d168570 (diff)
downloadqtwebchannel-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.cpp4
-rw-r--r--tests/auto/webchannel/tst_webchannel.cpp34
-rw-r--r--tests/auto/webchannel/tst_webchannel.h15
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();