Skip to content

Commit

Permalink
Browse files Browse the repository at this point in the history
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 <martin.jones@nokia.com>
  • Loading branch information
Glenn Watson authored and Qt by Nokia committed Mar 9, 2012
1 parent 2ecf1f5 commit 88a6f77
Show file tree
Hide file tree
Showing 2 changed files with 25 additions and 7 deletions.
18 changes: 11 additions & 7 deletions src/qml/qml/qquicklistmodel.cpp
Expand Up @@ -1110,14 +1110,18 @@ int ListElement::setJsProperty(const ListLayout::Role &role, v8::Handle<v8::Valu
} else if (d->IsNumber()) {
roleIndex = setDoubleProperty(role, d->NumberValue());
} else if (d->IsArray()) {
ListModel *subModel = new ListModel(role.subLayout, 0, -1);
v8::Handle<v8::Array> subArray = v8::Handle<v8::Array>::Cast(d);
int arrayLength = subArray->Length();
for (int j=0 ; j < arrayLength ; ++j) {
v8::Handle<v8::Object> 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<v8::Array> subArray = v8::Handle<v8::Array>::Cast(d);
int arrayLength = subArray->Length();
for (int j=0 ; j < arrayLength ; ++j) {
v8::Handle<v8::Object> 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()) {
Expand Down
14 changes: 14 additions & 0 deletions tests/auto/qml/qquicklistmodel/tst_qquicklistmodel.cpp
Expand Up @@ -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)
Expand Down Expand Up @@ -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, "<Unknown File>: 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"

0 comments on commit 88a6f77

Please sign in to comment.