Avoid crash when a QML signal is connected to a non-void slot
authorJ-P Nurmi <jpnurmi@digia.com>
Mon, 21 Oct 2013 12:43:19 +0000 (14:43 +0200)
committerThe Qt Project <gerrit-noreply@qt-project.org>
Tue, 22 Oct 2013 11:51:33 +0000 (13:51 +0200)
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 <simon.hausmann@digia.com>
src/qml/jsruntime/qv4qobjectwrapper.cpp
tests/auto/qml/qqmlecmascript/data/qtbug_32801.qml [new file with mode: 0644]
tests/auto/qml/qqmlecmascript/testtypes.h
tests/auto/qml/qqmlecmascript/tst_qqmlecmascript.cpp

index 3bca862..1fd47c7 100644 (file)
@@ -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<QJSValue>()) {
         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 (file)
index 0000000..c305ba7
--- /dev/null
@@ -0,0 +1,10 @@
+import Qt.test 1.0
+import QtQuick 2.0
+
+MyQmlObject {
+    signal testSignal(string arg)
+
+    function emitTestSignal() {
+        testSignal("test")
+    }
+}
index c6f6de7..0fdcdaf 100644 (file)
@@ -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;
index 47b7a66..e764ae7 100644 (file)
@@ -306,6 +306,7 @@ private slots:
     void jsOwnedObjectsDeletedOnEngineDestroy();
     void numberParsing();
     void stringParsing();
+    void qtbug_32801();
 
 private:
 //    static void propertyVarWeakRefCallback(v8::Persistent<v8::Value> object, void* parameter);
@@ -7288,6 +7289,18 @@ void tst_qqmlecmascript::stringParsing()
     }
 }
 
+void tst_qqmlecmascript::qtbug_32801()
+{
+    QQmlComponent component(&engine, testFileUrl("qtbug_32801.qml"));
+
+    QScopedPointer<QObject> 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"