From 0dd867535bebf6db673d4f03959e62e94ff35ba2 Mon Sep 17 00:00:00 2001 From: Chris Adams Date: Fri, 4 Nov 2011 14:38:38 +1000 Subject: [PATCH] Fix crash in object serialization due to sequences Commit c177691118e4e2bace9b5c1f4f57343190e6ad64 added support for sequences, but in doing so, introduced a crash bug into worker thread object serialisation. This commit fixes the bug by ensuring that the object resource type is checked prior to serialisation. Change-Id: I4ef9e4d0865a337c4fe6e8f1cd40cf4462ca7a60 Reviewed-by: Martin Jones --- src/declarative/qml/v8/qv8worker.cpp | 32 ++++++++++--------- .../data/externalObjectWorker.qml | 14 ++++++++ .../tst_qdeclarativeworkerscript.cpp | 11 +++++++ 3 files changed, 42 insertions(+), 15 deletions(-) create mode 100644 tests/auto/declarative/qdeclarativeworkerscript/data/externalObjectWorker.qml diff --git a/src/declarative/qml/v8/qv8worker.cpp b/src/declarative/qml/v8/qv8worker.cpp index 16e5abf..f0d9906 100644 --- a/src/declarative/qml/v8/qv8worker.cpp +++ b/src/declarative/qml/v8/qv8worker.cpp @@ -257,23 +257,25 @@ void QV8Worker::serialize(QByteArray &data, v8::Handle v, QV8Engine * if (v->IsObject()) { v8::Handle seqObj = v->ToObject(); QV8ObjectResource *r = static_cast(seqObj->GetExternalResource()); - QVariant sequenceVariant = engine->sequenceWrapper()->toVariant(r); - if (!sequenceVariant.isNull()) { - // valid sequence. we generate a length (sequence length + 1 for the sequence type) - uint32_t seqLength = engine->sequenceWrapper()->sequenceLength(r); - uint32_t length = seqLength + 1; - if (length > 0xFFFFFF) { - push(data, valueheader(WorkerUndefined)); + if (r->resourceType() == QV8ObjectResource::SequenceType) { + QVariant sequenceVariant = engine->sequenceWrapper()->toVariant(r); + if (!sequenceVariant.isNull()) { + // valid sequence. we generate a length (sequence length + 1 for the sequence type) + uint32_t seqLength = engine->sequenceWrapper()->sequenceLength(r); + uint32_t length = seqLength + 1; + if (length > 0xFFFFFF) { + push(data, valueheader(WorkerUndefined)); + return; + } + reserve(data, sizeof(quint32) + length * sizeof(quint32)); + push(data, valueheader(WorkerSequence, length)); + serialize(data, v8::Integer::New(sequenceVariant.userType()), engine); // sequence type + for (uint32_t ii = 0; ii < seqLength; ++ii) { + serialize(data, seqObj->Get(ii), engine); // sequence elements + } + return; } - reserve(data, sizeof(quint32) + length * sizeof(quint32)); - push(data, valueheader(WorkerSequence, length)); - serialize(data, v8::Integer::New(sequenceVariant.userType()), engine); // sequence type - for (uint32_t ii = 0; ii < seqLength; ++ii) { - serialize(data, seqObj->Get(ii), engine); // sequence elements - } - - return; } } diff --git a/tests/auto/declarative/qdeclarativeworkerscript/data/externalObjectWorker.qml b/tests/auto/declarative/qdeclarativeworkerscript/data/externalObjectWorker.qml new file mode 100644 index 0000000..1dae608 --- /dev/null +++ b/tests/auto/declarative/qdeclarativeworkerscript/data/externalObjectWorker.qml @@ -0,0 +1,14 @@ +import QtQuick 2.0 + +Item { + id: root + + function testExternalObject() { + worker.sendMessage(Qt.vector3d(1,2,3)); + } + + WorkerScript { + id: worker + source: "script.js" + } +} diff --git a/tests/auto/declarative/qdeclarativeworkerscript/tst_qdeclarativeworkerscript.cpp b/tests/auto/declarative/qdeclarativeworkerscript/tst_qdeclarativeworkerscript.cpp index bb7921c..eb3413e 100644 --- a/tests/auto/declarative/qdeclarativeworkerscript/tst_qdeclarativeworkerscript.cpp +++ b/tests/auto/declarative/qdeclarativeworkerscript/tst_qdeclarativeworkerscript.cpp @@ -69,6 +69,7 @@ private slots: void messaging_data(); void messaging_sendQObjectList(); void messaging_sendJsObject(); + void messaging_sendExternalObject(); void script_with_pragma(); void script_included(); void scriptError_onLoad(); @@ -200,6 +201,16 @@ void tst_QDeclarativeWorkerScript::messaging_sendJsObject() delete worker; } +void tst_QDeclarativeWorkerScript::messaging_sendExternalObject() +{ + QDeclarativeComponent component(&m_engine, TESTDATA("externalObjectWorker.qml")); + QObject *obj = component.create(); + QVERIFY(obj); + QMetaObject::invokeMethod(obj, "testExternalObject"); + QTest::qWait(100); // shouldn't crash. + delete obj; +} + void tst_QDeclarativeWorkerScript::script_with_pragma() { QVariant value(100); -- 1.7.2.5