diff options
author | Arno Rehn <a.rehn@menlosystems.com> | 2019-07-11 20:51:07 +0200 |
---|---|---|
committer | Arno Rehn <a.rehn@menlosystems.com> | 2019-07-26 15:47:47 +0200 |
commit | 29496e3f08e20398e253e6d32bb95879a1a68978 (patch) | |
tree | 2896ce0f5f0beaa694d70342646143a1e5f69063 | |
parent | 25fb211a32890a1bdd2b28b9727f6806a88d221c (diff) |
Correctly link transports to implicitly wrapped objects
When an object is wrapped as consequence of a property update or signal
emission, wrapResult() assigns it the parent object's list of transports.
It didn't, however, establish the reverse relation, i.e from transport
to object. This resulted in dangling pointers after client disconnects
and subsequent crashes.
This patch fixes the bug.
Change-Id: I5d20269c453902bf2883dfcab1f3ab5d0757c2cd
Reviewed-by: Frederik Gladhorn <frederik.gladhorn@qt.io>
-rw-r--r-- | src/webchannel/qmetaobjectpublisher.cpp | 6 | ||||
-rw-r--r-- | tests/auto/webchannel/tst_webchannel.cpp | 30 | ||||
-rw-r--r-- | tests/auto/webchannel/tst_webchannel.h | 1 |
3 files changed, 36 insertions, 1 deletions
diff --git a/src/webchannel/qmetaobjectpublisher.cpp b/src/webchannel/qmetaobjectpublisher.cpp index 102cbda..e23921d 100644 --- a/src/webchannel/qmetaobjectpublisher.cpp +++ b/src/webchannel/qmetaobjectpublisher.cpp @@ -739,15 +739,19 @@ QJsonValue QMetaObjectPublisher::wrapResult(const QVariant &result, QWebChannelA ObjectInfo oi(object); if (transport) { oi.transports.append(transport); + transportedWrappedObjects.insert(transport, id); } else { // use the transports from the parent object oi.transports = wrappedObjects.value(parentObjectId).transports; // or fallback to all transports if the parent is not wrapped if (oi.transports.isEmpty()) oi.transports = webChannel->d_func()->transports; + + for (auto transport : qAsConst(oi.transports)) { + transportedWrappedObjects.insert(transport, id); + } } wrappedObjects.insert(id, oi); - transportedWrappedObjects.insert(transport, id); initializePropertyUpdates(object, classInfo); } else if (wrappedObjects.contains(id)) { diff --git a/tests/auto/webchannel/tst_webchannel.cpp b/tests/auto/webchannel/tst_webchannel.cpp index ffaebba..4a66bdd 100644 --- a/tests/auto/webchannel/tst_webchannel.cpp +++ b/tests/auto/webchannel/tst_webchannel.cpp @@ -757,6 +757,36 @@ void TestWebChannel::testUnwrapObject() } } +void TestWebChannel::testTransportWrapObjectProperties() +{ + QWebChannel channel; + + TestObject obj; + obj.setObjectName("testObject"); + channel.registerObject(obj.objectName(), &obj); + + DummyTransport *dummyTransport = new DummyTransport(this); + channel.connectTo(dummyTransport); + channel.d_func()->publisher->initializeClient(dummyTransport); + channel.d_func()->publisher->setClientIsIdle(true); + + QCOMPARE(channel.d_func()->publisher->transportedWrappedObjects.size(), 0); + + QObject objPropObject; + objPropObject.setObjectName("foobar"); + + obj.setObjectProperty(&objPropObject); + + channel.d_func()->publisher->sendPendingPropertyUpdates(); + + QCOMPARE(channel.d_func()->publisher->wrappedObjects.size(), 1); + const QString wrappedObjId = channel.d_func()->publisher->wrappedObjects.keys()[0]; + + QCOMPARE(channel.d_func()->publisher->transportedWrappedObjects.size(), 1); + QCOMPARE(channel.d_func()->publisher->transportedWrappedObjects.keys()[0], dummyTransport); + QCOMPARE(channel.d_func()->publisher->transportedWrappedObjects.values()[0], wrappedObjId); +} + void TestWebChannel::testRemoveUnusedTransports() { QWebChannel channel; diff --git a/tests/auto/webchannel/tst_webchannel.h b/tests/auto/webchannel/tst_webchannel.h index 8ca1cdd..7cfce06 100644 --- a/tests/auto/webchannel/tst_webchannel.h +++ b/tests/auto/webchannel/tst_webchannel.h @@ -327,6 +327,7 @@ private slots: void testDisconnect(); void testWrapRegisteredObject(); void testUnwrapObject(); + void testTransportWrapObjectProperties(); void testRemoveUnusedTransports(); void testPassWrappedObjectBack(); void testWrapValues(); |