aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorLars Knoll <lars.knoll@digia.com>2013-11-18 13:54:33 +0100
committerThe Qt Project <gerrit-noreply@qt-project.org>2013-11-18 15:53:57 +0100
commit95d35ab188665281f54095e52948c9aad08e364d (patch)
treeeb84cad23b662dcaf809a993cf5e3f7e9c54e476
parent3d145175fd50b3fe31c62348307c995717d4200d (diff)
Fix interaction between head room and appending in arrays
We reserve space on both ends of the JS array for appending and prepending. Make sure they interact well with each other and don't cause any memory corruption. Task-number: QTBUG-34853 Change-Id: I184280178690e3cb12ab9b199a8436b32383af38 Reviewed-by: Simon Hausmann <simon.hausmann@digia.com>
-rw-r--r--src/qml/jsruntime/qv4arrayobject.cpp1
-rw-r--r--src/qml/jsruntime/qv4object.cpp12
-rw-r--r--src/qml/jsruntime/qv4object_p.h1
-rw-r--r--tests/auto/qml/qqmlecmascript/tst_qqmlecmascript.cpp13
4 files changed, 20 insertions, 7 deletions
diff --git a/src/qml/jsruntime/qv4arrayobject.cpp b/src/qml/jsruntime/qv4arrayobject.cpp
index 5422bff800..a0f0345b8b 100644
--- a/src/qml/jsruntime/qv4arrayobject.cpp
+++ b/src/qml/jsruntime/qv4arrayobject.cpp
@@ -572,6 +572,7 @@ ReturnedValue ArrayPrototype::method_unshift(CallContext *ctx)
--instance->arrayOffset;
--instance->arrayData;
++instance->arrayDataLen;
+ ++instance->arrayAlloc;
if (instance->arrayAttributes) {
--instance->arrayAttributes;
*instance->arrayAttributes = Attr_Data;
diff --git a/src/qml/jsruntime/qv4object.cpp b/src/qml/jsruntime/qv4object.cpp
index 099b5a5480..df2f6ca3f4 100644
--- a/src/qml/jsruntime/qv4object.cpp
+++ b/src/qml/jsruntime/qv4object.cpp
@@ -1319,19 +1319,17 @@ void Object::arrayReserve(uint n)
off = arrayOffset;
}
arrayAlloc = qMax(n, 2*arrayAlloc);
- Property *newArrayData = new Property[arrayAlloc];
+ Property *newArrayData = new Property[arrayAlloc + off];
if (arrayData) {
- memcpy(newArrayData, arrayData, sizeof(Property)*arrayDataLen);
+ memcpy(newArrayData + off, arrayData, sizeof(Property)*arrayDataLen);
delete [] (arrayData - off);
}
- arrayData = newArrayData;
+ arrayData = newArrayData + off;
if (sparseArray) {
for (uint i = arrayFreeList; i < arrayAlloc; ++i) {
arrayData[i].value = Primitive::emptyValue();
arrayData[i].value = Primitive::fromInt32(i + 1);
}
- } else {
- arrayOffset = 0;
}
if (arrayAttributes) {
@@ -1354,7 +1352,9 @@ void Object::ensureArrayAttributes()
return;
flags &= ~SimpleArray;
- arrayAttributes = new PropertyAttributes[arrayAlloc];
+ uint off = sparseArray ? 0 : arrayOffset;
+ arrayAttributes = new PropertyAttributes[arrayAlloc + off];
+ arrayAttributes += off;
for (uint i = 0; i < arrayDataLen; ++i)
arrayAttributes[i] = Attr_Data;
for (uint i = arrayDataLen; i < arrayAlloc; ++i)
diff --git a/src/qml/jsruntime/qv4object_p.h b/src/qml/jsruntime/qv4object_p.h
index 0d5955a0e7..daef18d4e2 100644
--- a/src/qml/jsruntime/qv4object_p.h
+++ b/src/qml/jsruntime/qv4object_p.h
@@ -210,7 +210,6 @@ struct Q_QML_EXPORT Object: Managed {
delete [] arrayAttributes;
arrayAttributes = newAttrs + arrayOffset;
}
- arrayAlloc += arrayOffset;
}
public:
diff --git a/tests/auto/qml/qqmlecmascript/tst_qqmlecmascript.cpp b/tests/auto/qml/qqmlecmascript/tst_qqmlecmascript.cpp
index 95f03d2c5b..7c1eb7d54b 100644
--- a/tests/auto/qml/qqmlecmascript/tst_qqmlecmascript.cpp
+++ b/tests/auto/qml/qqmlecmascript/tst_qqmlecmascript.cpp
@@ -307,6 +307,7 @@ private slots:
void updateCall();
void numberParsing();
void stringParsing();
+ void push_and_shift();
void qtbug_32801();
void thisObject();
void qtbug_33754();
@@ -7318,6 +7319,18 @@ void tst_qqmlecmascript::stringParsing()
}
}
+void tst_qqmlecmascript::push_and_shift()
+{
+ QJSEngine e;
+ const QString program =
+ "var array = []; "
+ "for (var i = 0; i < 10000; i++) {"
+ " array.push(5); array.unshift(5); array.push(5);"
+ "}"
+ "array.length;";
+ QVERIFY(e.evaluate(program).toNumber() == 30000);
+}
+
void tst_qqmlecmascript::qtbug_32801()
{
QQmlComponent component(&engine, testFileUrl("qtbug_32801.qml"));