From 88a6f771f203814e118f71196c800c93ee769055 Mon Sep 17 00:00:00 2001 From: Glenn Watson Date: Fri, 9 Mar 2012 09:19:35 +1000 Subject: [PATCH] Fix crash in listmodel when data is assigned incorrectly. If a listmodel with static role types is created, it would crash if a role was assigned a value type such as string, and then subsequently assigned an array (sub list) value from a dynamic meta object (created when using get() from JS). Change-Id: Ibfd0b0b40be13b04103b49462cfae42a5c9f9fb9 Reviewed-by: Martin Jones --- src/qml/qml/qquicklistmodel.cpp | 18 +++++++++++------- tests/auto/qml/qquicklistmodel/tst_qquicklistmodel.cpp | 14 ++++++++++++++ 2 files changed, 25 insertions(+), 7 deletions(-) diff --git a/src/qml/qml/qquicklistmodel.cpp b/src/qml/qml/qquicklistmodel.cpp index 30c4f5d..48187ca 100644 --- a/src/qml/qml/qquicklistmodel.cpp +++ b/src/qml/qml/qquicklistmodel.cpp @@ -1110,14 +1110,18 @@ int ListElement::setJsProperty(const ListLayout::Role &role, v8::HandleIsNumber()) { roleIndex = setDoubleProperty(role, d->NumberValue()); } else if (d->IsArray()) { - ListModel *subModel = new ListModel(role.subLayout, 0, -1); - v8::Handle subArray = v8::Handle::Cast(d); - int arrayLength = subArray->Length(); - for (int j=0 ; j < arrayLength ; ++j) { - v8::Handle subObject = subArray->Get(j)->ToObject(); - subModel->append(subObject, eng); + if (role.type == ListLayout::Role::List) { + ListModel *subModel = new ListModel(role.subLayout, 0, -1); + v8::Handle subArray = v8::Handle::Cast(d); + int arrayLength = subArray->Length(); + for (int j=0 ; j < arrayLength ; ++j) { + v8::Handle subObject = subArray->Get(j)->ToObject(); + subModel->append(subObject, eng); + } + roleIndex = setListProperty(role, subModel); + } else { + qmlInfo(0) << QString::fromLatin1("Can't assign to existing role '%1' of different type [%2 -> %3]").arg(role.name).arg(roleTypeName(role.type)).arg(roleTypeName(ListLayout::Role::List)); } - roleIndex = setListProperty(role, subModel); } else if (d->IsBoolean()) { roleIndex = setBoolProperty(role, d->BooleanValue()); } else if (d->IsObject()) { diff --git a/tests/auto/qml/qquicklistmodel/tst_qquicklistmodel.cpp b/tests/auto/qml/qquicklistmodel/tst_qquicklistmodel.cpp index 3fcce60..69a8d2e 100644 --- a/tests/auto/qml/qquicklistmodel/tst_qquicklistmodel.cpp +++ b/tests/auto/qml/qquicklistmodel/tst_qquicklistmodel.cpp @@ -139,6 +139,7 @@ private slots: void role_mode(); void dynamic_role(); void dynamic_role_data(); + void string_to_list_crash(); }; bool tst_qquicklistmodel::compareVariantList(const QVariantList &testList, QVariant object) @@ -1627,6 +1628,19 @@ void tst_qquicklistmodel::dynamic_role() qApp->processEvents(); } +void tst_qquicklistmodel::string_to_list_crash() +{ + QQmlEngine engine; + QQuickListModel model; + QQmlEngine::setContextForObject(&model,engine.rootContext()); + engine.rootContext()->setContextObject(&model); + QString script = QLatin1String("{append({'a':'data'});get(0).a = [{'x':123}]}"); + QTest::ignoreMessage(QtWarningMsg, ": Can't assign to existing role 'a' of different type [String -> List]"); + QQmlExpression e(engine.rootContext(), &model, script); + // Don't crash! + e.evaluate(); +} + QTEST_MAIN(tst_qquicklistmodel) #include "tst_qquicklistmodel.moc" -- 2.7.4