From d4cdc4542609e61d04802902d73c693faa8d8969 Mon Sep 17 00:00:00 2001 From: Olivier Goffart Date: Tue, 18 Apr 2017 12:08:12 +0200 Subject: Fix QMetaMethod::invoke and automatic type registration This was simply not working for two reasons: - The index passed to QMetaObject::metacall was not right (there was an offset because of the return type) - If the registration succeeded, the arguments were not even initialized. The tests in tst_moc always called QMetaMethod::parameterType before calling invoke, which was properly registering the type. So this was not seen in the tests before. [ChangeLog][QtCore][QMetaMethod] Fixed crash in invoke() with QueuedConnection and types whose metatype gets automatically registered. Task-number: QTBUG-60185 Change-Id: I4247628484214fba0a8acc1813ed8f112f59c888 Reviewed-by: Thiago Macieira --- src/corelib/kernel/qmetaobject.cpp | 12 +++++---- .../corelib/kernel/qmetaobject/tst_qmetaobject.cpp | 29 ++++++++++++++++++++++ 2 files changed, 36 insertions(+), 5 deletions(-) diff --git a/src/corelib/kernel/qmetaobject.cpp b/src/corelib/kernel/qmetaobject.cpp index 2e0dd8e5d2..a8003f7e46 100644 --- a/src/corelib/kernel/qmetaobject.cpp +++ b/src/corelib/kernel/qmetaobject.cpp @@ -2241,12 +2241,10 @@ bool QMetaMethod::invoke(QObject *object, for (int i = 1; i < paramCount; ++i) { types[i] = QMetaType::type(typeNames[i]); - if (types[i] != QMetaType::UnknownType) { - args[i] = QMetaType::create(types[i], param[i]); - ++nargs; - } else if (param[i]) { + if (types[i] == QMetaType::UnknownType && param[i]) { // Try to register the type and try again before reporting an error. - void *argv[] = { &types[i], &i }; + int index = nargs - 1; + void *argv[] = { &types[i], &index }; QMetaObject::metacall(object, QMetaObject::RegisterMethodArgumentMetaType, idx_relative + idx_offset, argv); if (types[i] == -1) { @@ -2261,6 +2259,10 @@ bool QMetaMethod::invoke(QObject *object, return false; } } + if (types[i] != QMetaType::UnknownType) { + args[i] = QMetaType::create(types[i], param[i]); + ++nargs; + } } QCoreApplication::postEvent(object, new QMetaCallEvent(idx_offset, idx_relative, callFunction, diff --git a/tests/auto/corelib/kernel/qmetaobject/tst_qmetaobject.cpp b/tests/auto/corelib/kernel/qmetaobject/tst_qmetaobject.cpp index fd32dc1ef8..e793d71fe2 100644 --- a/tests/auto/corelib/kernel/qmetaobject/tst_qmetaobject.cpp +++ b/tests/auto/corelib/kernel/qmetaobject/tst_qmetaobject.cpp @@ -206,6 +206,7 @@ private slots: void invokeMetaConstructor(); void invokeTypedefTypes(); void invokeException(); + void invokeQueuedAutoRegister(); void qtMetaObjectInheritance(); void normalizedSignature_data(); void normalizedSignature(); @@ -377,6 +378,7 @@ class QtTestObject: public QObject public: QtTestObject(); + QtTestObject(const QString &s) : slotResult(s) {} Q_INVOKABLE QtTestObject(QObject *parent); public slots: @@ -416,6 +418,15 @@ public slots: return s2; } + void slotWithRegistrableArgument(QtTestObject *o1, QPointer o2, + QSharedPointer o3, QWeakPointer o4, + QVector o5, QList o6) + { + slotResult = QLatin1String("slotWithRegistrableArgument:") + o1->slotResult + o2->slotResult + + o3->slotResult + o4.data()->slotResult + QString::number(o5.size()) + + QString::number(o6.size()); + } + signals: void sig0(); QString sig1(QString s1); @@ -944,6 +955,24 @@ void tst_QMetaObject::invokeException() #endif } +void tst_QMetaObject::invokeQueuedAutoRegister() +{ + QtTestObject obj; + + auto shared = QSharedPointer::create(QStringLiteral("myShared-")); + + QVERIFY(QMetaObject::invokeMethod( + &obj, "slotWithRegistrableArgument", Qt::QueuedConnection, + Q_ARG(QtTestObject *, shared.data()), Q_ARG(QPointer, shared.data()), + Q_ARG(QSharedPointer, shared), Q_ARG(QWeakPointer, shared), + Q_ARG(QVector, QVector()), + Q_ARG(QList, QList()))); + QVERIFY(obj.slotResult.isEmpty()); + qApp->processEvents(QEventLoop::AllEvents); + QCOMPARE(obj.slotResult, + QString("slotWithRegistrableArgument:myShared-myShared-myShared-myShared-00")); +} + void tst_QMetaObject::normalizedSignature_data() { QTest::addColumn("signature"); -- cgit v1.2.3