diff options
author | Lars Knoll <lars.knoll@digia.com> | 2013-09-20 15:13:14 +0200 |
---|---|---|
committer | The Qt Project <gerrit-noreply@qt-project.org> | 2013-09-22 15:29:00 +0200 |
commit | 1fb3cd12c8cdc76d1986736fbd60b5810cc17045 (patch) | |
tree | 700e7e2d29231a57c945e53fe71e2ab2250e8f2a | |
parent | 47bf40dd49f90b52cc1b545b2be3035d48d6199e (diff) |
Fix cases where mark() would access uninitialized memory
Change-Id: I4e07e20d30ba57759a0ece1c298a02b098718b33
Reviewed-by: Simon Hausmann <simon.hausmann@digia.com>
-rw-r--r-- | src/qml/compiler/qv4compileddata.cpp | 7 | ||||
-rw-r--r-- | src/qml/compiler/qv4isel_masm.cpp | 1 | ||||
-rw-r--r-- | src/qml/compiler/qv4isel_moth.cpp | 1 | ||||
-rw-r--r-- | src/qml/jsruntime/qv4arrayobject.cpp | 82 | ||||
-rw-r--r-- | src/qml/jsruntime/qv4function.cpp | 2 | ||||
-rw-r--r-- | src/qml/jsruntime/qv4functionobject.cpp | 15 | ||||
-rw-r--r-- | src/qml/jsruntime/qv4jsonobject.cpp | 5 | ||||
-rw-r--r-- | src/qml/jsruntime/qv4object.cpp | 10 | ||||
-rw-r--r-- | src/qml/jsruntime/qv4qobjectwrapper.cpp | 5 | ||||
-rw-r--r-- | src/qml/jsruntime/qv4regexpobject.cpp | 2 | ||||
-rw-r--r-- | src/qml/jsruntime/qv4serialize.cpp | 2 | ||||
-rw-r--r-- | src/qml/jsruntime/qv4value_p.h | 2 | ||||
-rw-r--r-- | src/qml/qml/qqmlcomponent.cpp | 5 | ||||
-rw-r--r-- | src/qml/qml/qqmllocale.cpp | 6 | ||||
-rw-r--r-- | src/qml/qml/v8/qv8engine.cpp | 20 |
15 files changed, 87 insertions, 78 deletions
diff --git a/src/qml/compiler/qv4compileddata.cpp b/src/qml/compiler/qv4compileddata.cpp index cc1f27c064..4139a7ee0d 100644 --- a/src/qml/compiler/qv4compileddata.cpp +++ b/src/qml/compiler/qv4compileddata.cpp @@ -76,10 +76,14 @@ QV4::Function *CompilationUnit::linkToEngine(ExecutionEngine *engine) assert(!runtimeStrings); assert(data); runtimeStrings = (QV4::SafeString *)malloc(data->stringTableSize * sizeof(QV4::SafeString)); + // memset the strings to 0 in case a GC run happens while we're within the loop below + memset(runtimeStrings, 0, data->stringTableSize * sizeof(QV4::SafeString)); for (int i = 0; i < data->stringTableSize; ++i) runtimeStrings[i] = engine->newIdentifier(data->stringAt(i)); runtimeRegularExpressions = new QV4::Value[data->regexpTableSize]; + // memset the regexps to 0 in case a GC run happens while we're within the loop below + memset(runtimeRegularExpressions, 0, data->regexpTableSize * sizeof(QV4::Value)); for (int i = 0; i < data->regexpTableSize; ++i) { const CompiledData::RegExp *re = data->regexpAt(i); int flags = 0; @@ -166,7 +170,8 @@ void CompilationUnit::markObjects() for (int i = 0; i < data->regexpTableSize; ++i) runtimeRegularExpressions[i].mark(); for (int i = 0; i < runtimeFunctions.count(); ++i) - runtimeFunctions[i]->mark(); + if (runtimeFunctions[i]) + runtimeFunctions[i]->mark(); } QString Binding::valueAsString(const Unit *unit) const diff --git a/src/qml/compiler/qv4isel_masm.cpp b/src/qml/compiler/qv4isel_masm.cpp index c723471c9f..6d69e57113 100644 --- a/src/qml/compiler/qv4isel_masm.cpp +++ b/src/qml/compiler/qv4isel_masm.cpp @@ -75,6 +75,7 @@ CompilationUnit::~CompilationUnit() void CompilationUnit::linkBackendToEngine(ExecutionEngine *engine) { runtimeFunctions.resize(data->functionTableSize); + runtimeFunctions.fill(0); for (int i = 0 ;i < runtimeFunctions.size(); ++i) { const CompiledData::Function *compiledFunction = data->functionAt(i); diff --git a/src/qml/compiler/qv4isel_moth.cpp b/src/qml/compiler/qv4isel_moth.cpp index b3e837d158..90d261620a 100644 --- a/src/qml/compiler/qv4isel_moth.cpp +++ b/src/qml/compiler/qv4isel_moth.cpp @@ -1059,6 +1059,7 @@ CompilationUnit::~CompilationUnit() void CompilationUnit::linkBackendToEngine(QV4::ExecutionEngine *engine) { runtimeFunctions.resize(data->functionTableSize); + runtimeFunctions.fill(0); for (int i = 0 ;i < runtimeFunctions.size(); ++i) { const QV4::CompiledData::Function *compiledFunction = data->functionAt(i); diff --git a/src/qml/jsruntime/qv4arrayobject.cpp b/src/qml/jsruntime/qv4arrayobject.cpp index 492dfe139b..44687463e2 100644 --- a/src/qml/jsruntime/qv4arrayobject.cpp +++ b/src/qml/jsruntime/qv4arrayobject.cpp @@ -167,9 +167,11 @@ ReturnedValue ArrayPrototype::method_concat(SimpleCallContext *ctx) result->arraySet(0, thisObject); } + ScopedArrayObject elt(scope); for (uint i = 0; i < ctx->argumentCount; ++i) { - if (ArrayObject *elt = ctx->arguments[i].asArrayObject()) - result->arrayConcat(elt); + elt = ctx->arguments[i]; + if (elt) + result->arrayConcat(elt.getPointer()); else result->arraySet(getLength(ctx, result.getPointer()), ctx->arguments[i]); } @@ -188,17 +190,12 @@ ReturnedValue ArrayPrototype::method_join(SimpleCallContext *ctx) else r4 = arg->toQString(); - Scoped<Object> self(scope, ctx->thisObject); + ScopedObject self(scope, ctx->thisObject); ScopedValue length(scope, self->get(ctx->engine->id_length)); - const quint32 r2 = Value::toUInt32(length->isUndefined() ? 0 : length->toNumber()); + const quint32 r2 = length->isUndefined() ? 0 : length->toUInt32(); - static QSet<Object *> visitedArrayElements; - - if (! r2 || visitedArrayElements.contains(self.getPointer())) - return Value::fromString(ctx, QString()).asReturnedValue(); - - // avoid infinite recursion - visitedArrayElements.insert(self.getPointer()); + if (!r2) + return ctx->engine->newString(QString())->asReturnedValue(); QString R; @@ -234,8 +231,7 @@ ReturnedValue ArrayPrototype::method_join(SimpleCallContext *ctx) } } - visitedArrayElements.remove(self.getPointer()); - return Value::fromString(ctx, R).asReturnedValue(); + return ctx->engine->newString(R)->asReturnedValue(); } ReturnedValue ArrayPrototype::method_pop(SimpleCallContext *ctx) @@ -247,7 +243,7 @@ ReturnedValue ArrayPrototype::method_pop(SimpleCallContext *ctx) if (!len) { if (!instance->isArrayObject()) instance->put(ctx->engine->id_length, ScopedValue(scope, Value::fromInt32(0))); - return Value::undefinedValue().asReturnedValue(); + return Encode::undefined(); } ScopedValue result(scope, instance->getIndexed(len - 1)); @@ -269,9 +265,9 @@ ReturnedValue ArrayPrototype::method_push(SimpleCallContext *ctx) if (len + ctx->argumentCount < len) { // ughh... double l = len; + ScopedString s(scope); for (int i = 0; i < ctx->argumentCount; ++i) { - Value idx = Value::fromDouble(l + i); - ScopedString s(scope, idx.toString(ctx)); + s = Value::fromDouble(l + i).toString(ctx); instance->put(s, ctx->arguments[i]); } double newLen = l + ctx->argumentCount; @@ -307,17 +303,14 @@ ReturnedValue ArrayPrototype::method_push(SimpleCallContext *ctx) else instance->put(ctx->engine->id_length, ScopedValue(scope, Value::fromDouble(len))); - if (len < INT_MAX) - return Value::fromInt32(len).asReturnedValue(); - return Value::fromDouble((double)len).asReturnedValue(); - + return Encode(len); } ReturnedValue ArrayPrototype::method_reverse(SimpleCallContext *ctx) { Scope scope(ctx); - Object *instance = ctx->thisObject.toObject(ctx); - uint length = getLength(ctx, instance); + ScopedObject instance(scope, ctx->thisObject.toObject(ctx)); + uint length = getLength(ctx, instance.getPointer()); int lo = 0, hi = length - 1; @@ -336,14 +329,14 @@ ReturnedValue ArrayPrototype::method_reverse(SimpleCallContext *ctx) else instance->deleteIndexedProperty(hi); } - return Value::fromObject(instance).asReturnedValue(); + return instance.asReturnedValue(); } ReturnedValue ArrayPrototype::method_shift(SimpleCallContext *ctx) { Scope scope(ctx); - Object *instance = ctx->thisObject.toObject(ctx); - uint len = getLength(ctx, instance); + ScopedObject instance(scope, ctx->thisObject.toObject(ctx)); + uint len = getLength(ctx, instance.getPointer()); if (!len) { if (!instance->isArrayObject()) @@ -396,10 +389,10 @@ ReturnedValue ArrayPrototype::method_shift(SimpleCallContext *ctx) ReturnedValue ArrayPrototype::method_slice(SimpleCallContext *ctx) { Scope scope(ctx); - Object *o = ctx->thisObject.toObject(ctx); + ScopedObject o(scope, ctx->thisObject.toObject(ctx)); Scoped<ArrayObject> result(scope, ctx->engine->newArrayObject()); - uint len = ArrayPrototype::getLength(ctx, o); + uint len = getLength(ctx, o.getPointer()); double s = ScopedValue(scope, ctx->argument(0))->toInteger(); uint start; if (s < 0) @@ -447,8 +440,8 @@ ReturnedValue ArrayPrototype::method_sort(SimpleCallContext *ctx) ReturnedValue ArrayPrototype::method_splice(SimpleCallContext *ctx) { Scope scope(ctx); - Object *instance = ctx->thisObject.toObject(ctx); - uint len = getLength(ctx, instance); + ScopedObject instance(scope, ctx->thisObject.toObject(ctx)); + uint len = getLength(ctx, instance.getPointer()); Scoped<ArrayObject> newArray(scope, ctx->engine->newArrayObject()); @@ -462,12 +455,10 @@ ReturnedValue ArrayPrototype::method_splice(SimpleCallContext *ctx) uint deleteCount = (uint)qMin(qMax(ScopedValue(scope, ctx->argument(1))->toInteger(), 0.), (double)(len - start)); newArray->arrayReserve(deleteCount); - Property *pd = newArray->arrayData; for (uint i = 0; i < deleteCount; ++i) { - pd->value = Value::fromReturnedValue(instance->getIndexed(start + i)); - ++pd; + newArray->arrayData[i].value = Value::fromReturnedValue(instance->getIndexed(start + i)); + newArray->arrayDataLen = i + 1; } - newArray->arrayDataLen = deleteCount; newArray->setArrayLengthUnchecked(deleteCount); uint itemCount = ctx->argumentCount < 2 ? 0 : ctx->argumentCount - 2; @@ -509,11 +500,11 @@ ReturnedValue ArrayPrototype::method_splice(SimpleCallContext *ctx) ReturnedValue ArrayPrototype::method_unshift(SimpleCallContext *ctx) { Scope scope(ctx); - Object *instance = ctx->thisObject.toObject(ctx); - uint len = getLength(ctx, instance); + ScopedObject instance(scope, ctx->thisObject.toObject(ctx)); + uint len = getLength(ctx, instance.getPointer()); + ScopedValue v(scope); if (!instance->protoHasArray() && instance->arrayDataLen <= len) { - ScopedValue v(scope); for (int i = ctx->argumentCount - 1; i >= 0; --i) { v = ctx->argument(i); @@ -535,7 +526,6 @@ ReturnedValue ArrayPrototype::method_unshift(SimpleCallContext *ctx) } } } else { - ScopedValue v(scope); for (uint k = len; k > 0; --k) { bool exists; v = instance->getIndexed(k - 1, &exists); @@ -554,17 +544,15 @@ ReturnedValue ArrayPrototype::method_unshift(SimpleCallContext *ctx) else instance->put(ctx->engine->id_length, ScopedValue(scope, Value::fromDouble(newLen))); - if (newLen < INT_MAX) - return Value::fromInt32(newLen).asReturnedValue(); - return Value::fromDouble((double)newLen).asReturnedValue(); + return Encode(newLen); } ReturnedValue ArrayPrototype::method_indexOf(SimpleCallContext *ctx) { Scope scope(ctx); - Object *instance = ctx->thisObject.toObject(ctx); - uint len = getLength(ctx, instance); + ScopedObject instance(scope, ctx->thisObject.toObject(ctx)); + uint len = getLength(ctx, instance.getPointer()); if (!len) return Value::fromInt32(-1).asReturnedValue(); @@ -596,15 +584,15 @@ ReturnedValue ArrayPrototype::method_indexOf(SimpleCallContext *ctx) return Encode(-1); } - return instance->arrayIndexOf(searchValue, fromIndex, len, ctx, instance); + return instance->arrayIndexOf(searchValue, fromIndex, len, ctx, instance.getPointer()); } ReturnedValue ArrayPrototype::method_lastIndexOf(SimpleCallContext *ctx) { Scope scope(ctx); - Object *instance = ctx->thisObject.toObject(ctx); - uint len = getLength(ctx, instance); + ScopedObject instance(scope, ctx->thisObject.toObject(ctx)); + uint len = getLength(ctx, instance.getPointer()); if (!len) return Value::fromInt32(-1).asReturnedValue(); @@ -634,7 +622,7 @@ ReturnedValue ArrayPrototype::method_lastIndexOf(SimpleCallContext *ctx) bool exists; v = instance->getIndexed(k, &exists); if (exists && __qmljs_strict_equal(v, searchValue)) - return Value::fromDouble(k).asReturnedValue(); + return Encode(k); } return Value::fromInt32(-1).asReturnedValue(); } @@ -668,7 +656,7 @@ ReturnedValue ArrayPrototype::method_every(SimpleCallContext *ctx) r = callback->call(callData); ok = r->toBoolean(); } - return Value::fromBoolean(ok).asReturnedValue(); + return Encode(ok); } ReturnedValue ArrayPrototype::method_some(SimpleCallContext *ctx) diff --git a/src/qml/jsruntime/qv4function.cpp b/src/qml/jsruntime/qv4function.cpp index a39050aaf2..89eb5baba2 100644 --- a/src/qml/jsruntime/qv4function.cpp +++ b/src/qml/jsruntime/qv4function.cpp @@ -62,12 +62,14 @@ Function::Function(ExecutionEngine *engine, CompiledData::CompilationUnit *unit, name = compilationUnit->runtimeStrings[compiledFunction->nameIndex].asString(); formals.resize(compiledFunction->nFormals); + formals.fill(0); const quint32 *formalsIndices = compiledFunction->formalsTable(); for (int i = 0; i < compiledFunction->nFormals; ++i) formals[i] = engine->newString(unit->data->stringAt(formalsIndices[i])); locals.resize(compiledFunction->nLocals); + locals.fill(0); const quint32 *localsIndices = compiledFunction->localsTable(); for (int i = 0; i < compiledFunction->nLocals; ++i) locals[i] = engine->newString(unit->data->stringAt(localsIndices[i])); diff --git a/src/qml/jsruntime/qv4functionobject.cpp b/src/qml/jsruntime/qv4functionobject.cpp index a7332d65da..6c60a9964a 100644 --- a/src/qml/jsruntime/qv4functionobject.cpp +++ b/src/qml/jsruntime/qv4functionobject.cpp @@ -92,6 +92,9 @@ FunctionObject::FunctionObject(ExecutionContext *scope, const QString &name, boo , varCount(0) , function(0) { + // set the name to something here, so that a gc run a few lines below doesn't crash on it + this->name = scope->engine->id_undefined; + Scope s(scope); ScopedValue protectThis(s, this); ScopedString n(s, s.engine->newString(name)); @@ -108,7 +111,7 @@ FunctionObject::FunctionObject(InternalClass *ic) , function(0) { vtbl = &static_vtbl; - name = (QV4::String *)0; + name = engine()->id_undefined; type = Type_FunctionObject; needsActivation = false; @@ -125,6 +128,7 @@ FunctionObject::~FunctionObject() void FunctionObject::init(const StringRef n, bool createProto) { vtbl = &static_vtbl; + name = n; Scope s(engine()); ScopedValue protectThis(s, this); @@ -143,13 +147,8 @@ void FunctionObject::init(const StringRef n, bool createProto) memberData[Index_Prototype].value = proto.asValue(); } - if (n) { - name = n; - ScopedValue v(s, n.asReturnedValue()); - defineReadonlyProperty(scope->engine->id_name, v); - } else { - name = (QV4::String *)0; - } + ScopedValue v(s, n.asReturnedValue()); + defineReadonlyProperty(scope->engine->id_name, v); } ReturnedValue FunctionObject::newInstance() diff --git a/src/qml/jsruntime/qv4jsonobject.cpp b/src/qml/jsruntime/qv4jsonobject.cpp index f311dfd420..5d1669dd8b 100644 --- a/src/qml/jsruntime/qv4jsonobject.cpp +++ b/src/qml/jsruntime/qv4jsonobject.cpp @@ -1036,9 +1036,10 @@ QV4::ReturnedValue JsonObject::fromJsonArray(ExecutionEngine *engine, const QJso int size = array.size(); Scoped<ArrayObject> a(scope, engine->newArrayObject()); a->arrayReserve(size); - a->arrayDataLen = size; - for (int i = 0; i < size; i++) + for (int i = 0; i < size; i++) { a->arrayData[i].value = Value::fromReturnedValue(fromJsonValue(engine, array.at(i))); + a->arrayDataLen = i + 1; + } a->setArrayLengthUnchecked(size); return a.asReturnedValue(); } diff --git a/src/qml/jsruntime/qv4object.cpp b/src/qml/jsruntime/qv4object.cpp index c2a120c7f3..78b963e12d 100644 --- a/src/qml/jsruntime/qv4object.cpp +++ b/src/qml/jsruntime/qv4object.cpp @@ -1202,11 +1202,11 @@ void Object::arrayConcat(const ArrayObject *other) ensureArrayAttributes(); std::fill(arrayAttributes + arrayDataLen, arrayAttributes + oldSize, PropertyAttributes()); } - arrayDataLen = oldSize + other->arrayDataLen; if (other->arrayAttributes) { - for (int i = 0; i < arrayDataLen; ++i) { + for (int i = 0; i < other->arrayDataLen; ++i) { bool exists; arrayData[oldSize + i].value = Value::fromReturnedValue(const_cast<ArrayObject *>(other)->getIndexed(i, &exists)); + arrayDataLen = oldSize + i + 1; if (arrayAttributes) arrayAttributes[oldSize + i] = Attr_Data; if (!exists) { @@ -1215,6 +1215,7 @@ void Object::arrayConcat(const ArrayObject *other) } } } else { + arrayDataLen = oldSize + other->arrayDataLen; memcpy(arrayData + oldSize, other->arrayData, other->arrayDataLen*sizeof(Property)); if (arrayAttributes) std::fill(arrayAttributes + oldSize, arrayAttributes + oldSize + other->arrayDataLen, PropertyAttributes(Attr_Data)); @@ -1449,9 +1450,10 @@ ArrayObject::ArrayObject(ExecutionEngine *engine, const QStringList &list) // elements converted to JS Strings. int len = list.count(); arrayReserve(len); - for (int ii = 0; ii < len; ++ii) + for (int ii = 0; ii < len; ++ii) { arrayData[ii].value = Value::fromString(engine->newString(list.at(ii))); - arrayDataLen = len; + arrayDataLen = ii + 1; + } setArrayLengthUnchecked(len); } diff --git a/src/qml/jsruntime/qv4qobjectwrapper.cpp b/src/qml/jsruntime/qv4qobjectwrapper.cpp index e982989a4d..7e31797627 100644 --- a/src/qml/jsruntime/qv4qobjectwrapper.cpp +++ b/src/qml/jsruntime/qv4qobjectwrapper.cpp @@ -1611,9 +1611,10 @@ QV4::ReturnedValue CallArgument::toValue(QV8Engine *engine) QList<QObject *> &list = *qlistPtr; QV4::Scoped<ArrayObject> array(scope, v4->newArrayObject()); array->arrayReserve(list.count()); - array->arrayDataLen = list.count(); - for (int ii = 0; ii < list.count(); ++ii) + for (int ii = 0; ii < list.count(); ++ii) { array->arrayData[ii].value = Value::fromReturnedValue(QV4::QObjectWrapper::wrap(v4, list.at(ii))); + array->arrayDataLen = ii + 1; + } array->setArrayLengthUnchecked(list.count()); return array.asReturnedValue(); } else if (type == qMetaTypeId<QQmlV4Handle>()) { diff --git a/src/qml/jsruntime/qv4regexpobject.cpp b/src/qml/jsruntime/qv4regexpobject.cpp index 697d5e35d6..3f58f28b4b 100644 --- a/src/qml/jsruntime/qv4regexpobject.cpp +++ b/src/qml/jsruntime/qv4regexpobject.cpp @@ -333,8 +333,8 @@ ReturnedValue RegExpPrototype::method_exec(SimpleCallContext *ctx) int start = matchOffsets[i * 2]; int end = matchOffsets[i * 2 + 1]; array->arrayData[i].value = (start != -1 && end != -1) ? Value::fromString(ctx, s.mid(start, end - start)) : Value::undefinedValue(); + array->arrayDataLen = i + 1; } - array->arrayDataLen = len; array->setArrayLengthUnchecked(len); array->memberData[Index_ArrayIndex].value = Value::fromInt32(result); diff --git a/src/qml/jsruntime/qv4serialize.cpp b/src/qml/jsruntime/qv4serialize.cpp index cabe326d13..ae35d6c375 100644 --- a/src/qml/jsruntime/qv4serialize.cpp +++ b/src/qml/jsruntime/qv4serialize.cpp @@ -385,10 +385,10 @@ ReturnedValue Serialize::deserialize(const char *&data, QV8Engine *engine) int sequenceType = value->integerValue(); Scoped<ArrayObject> array(scope, v4->newArrayObject()); array->arrayReserve(seqLength); - array->arrayDataLen = seqLength; for (quint32 ii = 0; ii < seqLength; ++ii) { value = deserialize(data, engine); array->arrayData[ii].value = value; + array->arrayDataLen = ii + 1; } array->setArrayLengthUnchecked(seqLength); QVariant seqVariant = QV4::SequencePrototype::toVariant(array.asValue(), sequenceType, &succeeded); diff --git a/src/qml/jsruntime/qv4value_p.h b/src/qml/jsruntime/qv4value_p.h index bfad395b3b..ad884b6380 100644 --- a/src/qml/jsruntime/qv4value_p.h +++ b/src/qml/jsruntime/qv4value_p.h @@ -90,6 +90,8 @@ inline ExecutionEngine *Value::engine() const { } inline void Value::mark() const { + if (!val) + return; Managed *m = asManaged(); if (m) m->mark(); diff --git a/src/qml/qml/qqmlcomponent.cpp b/src/qml/qml/qqmlcomponent.cpp index 483ae908b4..cf3493a590 100644 --- a/src/qml/qml/qqmlcomponent.cpp +++ b/src/qml/qml/qqmlcomponent.cpp @@ -1244,12 +1244,13 @@ void QQmlComponent::createObject(QQmlV4Function *args) if (!valuemap.isUndefined()) { QQmlComponentExtension *e = componentExtension(v8engine); - QV4::Scoped<QV4::FunctionObject> f(scope, QV4::Script::evaluate(v4engine, QString::fromLatin1(INITIALPROPERTIES_SOURCE), args->qmlGlobal().asObject())); + QV4::ScopedValue f(scope, QV4::Script::evaluate(v4engine, QString::fromLatin1(INITIALPROPERTIES_SOURCE), args->qmlGlobal().asObject())); + Q_ASSERT(f->asFunctionObject()); QV4::ScopedCallData callData(scope, 2); callData->thisObject = QV4::Value::fromObject(v4engine->globalObject); callData->args[0] = object; callData->args[1] = valuemap; - f->call(callData); + f->asFunctionObject()->call(callData); } d->completeCreate(); diff --git a/src/qml/qml/qqmllocale.cpp b/src/qml/qml/qqmllocale.cpp index 85d200e8e6..c3c7d0282d 100644 --- a/src/qml/qml/qqmllocale.cpp +++ b/src/qml/qml/qqmllocale.cpp @@ -562,9 +562,11 @@ QV4::ReturnedValue QQmlLocaleData::method_get_uiLanguages(QV4::SimpleCallContext QStringList langs = locale.uiLanguages(); QV4::Scoped<QV4::ArrayObject> result(scope, ctx->engine->newArrayObject()); result->arrayReserve(langs.size()); - result->arrayDataLen = langs.size(); - for (int i = 0; i < langs.size(); ++i) + for (int i = 0; i < langs.size(); ++i) { result->arrayData[i].value = QV4::Value::fromString(ctx, langs.at(i)); + result->arrayDataLen = i + 1; + } + result->setArrayLengthUnchecked(langs.size()); return result.asReturnedValue(); diff --git a/src/qml/qml/v8/qv8engine.cpp b/src/qml/qml/v8/qv8engine.cpp index 70c3104ffa..b62e2150af 100644 --- a/src/qml/qml/v8/qv8engine.cpp +++ b/src/qml/qml/v8/qv8engine.cpp @@ -187,9 +187,10 @@ static QV4::ReturnedValue arrayFromStringList(QV8Engine *engine, const QStringLi QV4::Scoped<QV4::ArrayObject> a(scope, e->newArrayObject()); int len = list.count(); a->arrayReserve(len); - a->arrayDataLen = len; - for (int ii = 0; ii < len; ++ii) + for (int ii = 0; ii < len; ++ii) { a->arrayData[ii].value = QV4::Value::fromString(e->newString(list.at(ii))); + a->arrayDataLen = ii + 1; + } a->setArrayLengthUnchecked(len); return a.asReturnedValue(); } @@ -201,9 +202,10 @@ static QV4::ReturnedValue arrayFromVariantList(QV8Engine *engine, const QVariant QV4::Scoped<QV4::ArrayObject> a(scope, e->newArrayObject()); int len = list.count(); a->arrayReserve(len); - a->arrayDataLen = len; - for (int ii = 0; ii < len; ++ii) + for (int ii = 0; ii < len; ++ii) { a->arrayData[ii].value = QV4::Value::fromReturnedValue(engine->fromVariant(list.at(ii))); + a->arrayDataLen = ii + 1; + } a->setArrayLengthUnchecked(len); return a.asReturnedValue(); } @@ -314,9 +316,10 @@ QV4::ReturnedValue QV8Engine::fromVariant(const QVariant &variant) const QList<QObject *> &list = *(QList<QObject *>*)ptr; QV4::Scoped<QV4::ArrayObject> a(scope, m_v4Engine->newArrayObject()); a->arrayReserve(list.count()); - a->arrayDataLen = list.count(); - for (int ii = 0; ii < list.count(); ++ii) + for (int ii = 0; ii < list.count(); ++ii) { a->arrayData[ii].value = QV4::Value::fromReturnedValue(QV4::QObjectWrapper::wrap(m_v4Engine, list.at(ii))); + a->arrayDataLen = ii + 1; + } a->setArrayLengthUnchecked(list.count()); return a.asReturnedValue(); } else if (QMetaType::typeFlags(type) & QMetaType::PointerToQObject) { @@ -524,9 +527,10 @@ QV4::ReturnedValue QV8Engine::variantListToJS(const QVariantList &lst) QV4::Scope scope(m_v4Engine); QV4::Scoped<QV4::ArrayObject> a(scope, m_v4Engine->newArrayObject()); a->arrayReserve(lst.size()); - a->arrayDataLen = lst.size(); - for (int i = 0; i < lst.size(); i++) + for (int i = 0; i < lst.size(); i++) { a->arrayData[i].value = QV4::Value::fromReturnedValue(variantToJS(lst.at(i))); + a->arrayDataLen = i + 1; + } a->setArrayLengthUnchecked(lst.size()); return a.asReturnedValue(); } |