From: J-P Nurmi Date: Mon, 21 Oct 2013 12:43:19 +0000 (+0200) Subject: Avoid crash when a QML signal is connected to a non-void slot X-Git-Tag: upstream/5.2.1~169 X-Git-Url: http://review.tizen.org/git/?a=commitdiff_plain;h=4f1ed0948b99af617fa978f0f1b72e48a9fe774f;p=platform%2Fupstream%2Fqtdeclarative.git Avoid crash when a QML signal is connected to a non-void slot Don't pass a QVariant pointer for the return value when we're not interested in it and the return type might not even be a QVariant (that would be only true for QML methods). Task-number: QTBUG-32801 Change-Id: I8f14e40d8f94caef7e3d086b776735f0484dbf0e Reviewed-by: Simon Hausmann --- diff --git a/src/qml/jsruntime/qv4qobjectwrapper.cpp b/src/qml/jsruntime/qv4qobjectwrapper.cpp index 3bca862..1fd47c7 100644 --- a/src/qml/jsruntime/qv4qobjectwrapper.cpp +++ b/src/qml/jsruntime/qv4qobjectwrapper.cpp @@ -1436,14 +1436,15 @@ void *CallArgument::dataPtr() { if (type == -1) return qvariantPtr->data(); - else + else if (type != 0) return (void *)&allocData; + return 0; } void CallArgument::initAsType(int callType) { if (type != 0) { cleanup(); type = 0; } - if (callType == QMetaType::UnknownType) return; + if (callType == QMetaType::UnknownType || callType == QMetaType::Void) return; if (callType == qMetaTypeId()) { qjsValuePtr = new (&allocData) QJSValue(); @@ -1478,9 +1479,6 @@ void CallArgument::initAsType(int callType) } else if (callType == QMetaType::QJsonValue) { type = callType; jsonValuePtr = new (&allocData) QJsonValue(); - } else if (callType == QMetaType::Void) { - type = -1; - qvariantPtr = new (&allocData) QVariant(); } else { type = -1; qvariantPtr = new (&allocData) QVariant(callType, (void *)0); diff --git a/tests/auto/qml/qqmlecmascript/data/qtbug_32801.qml b/tests/auto/qml/qqmlecmascript/data/qtbug_32801.qml new file mode 100644 index 0000000..c305ba7 --- /dev/null +++ b/tests/auto/qml/qqmlecmascript/data/qtbug_32801.qml @@ -0,0 +1,10 @@ +import Qt.test 1.0 +import QtQuick 2.0 + +MyQmlObject { + signal testSignal(string arg) + + function emitTestSignal() { + testSignal("test") + } +} diff --git a/tests/auto/qml/qqmlecmascript/testtypes.h b/tests/auto/qml/qqmlecmascript/testtypes.h index c6f6de7..0fdcdaf 100644 --- a/tests/auto/qml/qqmlecmascript/testtypes.h +++ b/tests/auto/qml/qqmlecmascript/testtypes.h @@ -268,6 +268,7 @@ public slots: void qjsvalueMethod(const QJSValue &v) { m_qjsvalue = v; } void v8function(QQmlV4Function*); void registeredFlagMethod(Qt::MouseButtons v) { m_buttons = v; } + QString slotWithReturnValue(const QString &arg) { return arg; } private: friend class tst_qqmlecmascript; diff --git a/tests/auto/qml/qqmlecmascript/tst_qqmlecmascript.cpp b/tests/auto/qml/qqmlecmascript/tst_qqmlecmascript.cpp index 47b7a66..e764ae7 100644 --- a/tests/auto/qml/qqmlecmascript/tst_qqmlecmascript.cpp +++ b/tests/auto/qml/qqmlecmascript/tst_qqmlecmascript.cpp @@ -306,6 +306,7 @@ private slots: void jsOwnedObjectsDeletedOnEngineDestroy(); void numberParsing(); void stringParsing(); + void qtbug_32801(); private: // static void propertyVarWeakRefCallback(v8::Persistent object, void* parameter); @@ -7288,6 +7289,18 @@ void tst_qqmlecmascript::stringParsing() } } +void tst_qqmlecmascript::qtbug_32801() +{ + QQmlComponent component(&engine, testFileUrl("qtbug_32801.qml")); + + QScopedPointer obj(component.create()); + QVERIFY(obj != 0); + + // do not crash when a QML signal is connected to a non-void slot + connect(obj.data(), SIGNAL(testSignal(QString)), obj.data(), SLOT(slotWithReturnValue(QString))); + QVERIFY(QMetaObject::invokeMethod(obj.data(), "emitTestSignal")); +} + QTEST_MAIN(tst_qqmlecmascript) #include "tst_qqmlecmascript.moc"