diff options
author | Erik Verbruggen <erik.verbruggen@qt.io> | 2018-02-13 15:20:22 +0100 |
---|---|---|
committer | Simon Hausmann <simon.hausmann@qt.io> | 2018-02-14 21:01:55 +0000 |
commit | d19127807c193d612c6fee4f3418a8c8af9d262c (patch) | |
tree | 8e46dab79020b00bc843ed13aa608dcd69f6aa97 /src | |
parent | a484ea0d3666b57bb49e9284ff86af3ba87ce58b (diff) |
Clear the last value when removing properties
When we remove a property from an object, we shrink the used entries
by one (or 2 when an accessor is defined) by moving subsequent entries
"down" over the removed entry. We also have to set the last entry (or 2)
to Undefined, otherwise any heap objects referenced there would be
retained.
This cherry-pick into 5.9 also fixes an issue where the MemberData was
accessed out-of-bound: some entries stored in memory after the array
were copied in, resulting in invalid pointers, leading to a crash
whenever the garbage collector would run.
Task-number: QTBUG-66090
Change-Id: I75905fafd0d88891820d894a869b9714bc9807e0
Reviewed-by: Lars Knoll <lars.knoll@qt.io>
(cherry picked from commit 9e32901835de1c6729ac8bf228148c1e03c4c5a5)
Reviewed-by: Simon Hausmann <simon.hausmann@qt.io>
Diffstat (limited to 'src')
-rw-r--r-- | src/qml/jsruntime/qv4internalclass.cpp | 49 |
1 files changed, 11 insertions, 38 deletions
diff --git a/src/qml/jsruntime/qv4internalclass.cpp b/src/qml/jsruntime/qv4internalclass.cpp index 0bcd510541..fc5b7e7711 100644 --- a/src/qml/jsruntime/qv4internalclass.cpp +++ b/src/qml/jsruntime/qv4internalclass.cpp @@ -133,48 +133,21 @@ InternalClass::InternalClass(const QV4::InternalClass &other) static void insertHoleIntoPropertyData(Object *object, int idx) { - int inlineSize = object->d()->vtable()->nInlineProperties; - int icSize = object->internalClass()->size; - int from = qMax(idx, inlineSize); - int to = from + 1; - if (from < icSize) { - memmove(object->propertyData(to), object->propertyData(from), - (icSize - from - 1) * sizeof(Value)); - } - if (from == idx) - return; - if (inlineSize < icSize) - *object->propertyData(inlineSize) = *object->propertyData(inlineSize - 1); - from = idx; - to = from + 1; - if (from < inlineSize - 1) { - memmove(object->propertyData(to), object->propertyData(from), - (inlineSize - from - 1) * sizeof(Value)); - } + Heap::Object *o = object->d(); + int size = o->internalClass->size; + for (int i = size - 1; i > idx; --i) + *object->propertyData(i) = *o->propertyData(i - 1); } static void removeFromPropertyData(Object *object, int idx, bool accessor = false) { - int inlineSize = object->d()->vtable()->nInlineProperties; - int delta = (accessor ? 2 : 1); - int oldSize = object->internalClass()->size + delta; - int to = idx; - int from = to + delta; - if (from < inlineSize) { - memmove(object->propertyData(to), object->d()->propertyData(from), (inlineSize - from)*sizeof(Value)); - to = inlineSize - delta; - from = inlineSize; - } - if (to < inlineSize && from < oldSize) { - Q_ASSERT(from >= inlineSize); - memcpy(object->propertyData(to), object->d()->propertyData(from), (inlineSize - to)*sizeof(Value)); - to = inlineSize; - from = inlineSize + delta; - } - if (from < oldSize) { - Q_ASSERT(to >= inlineSize && from > to); - memmove(object->propertyData(to), object->d()->propertyData(from), (oldSize - to)*sizeof(Value)); - } + Heap::Object *o = object->d(); + int size = o->internalClass->size; + for (int i = idx; i < size; ++i) + *object->propertyData(i) = *o->propertyData(i + (accessor ? 2 : 1)); + *object->propertyData(size) = Primitive::undefinedValue(); + if (accessor) + *object->propertyData(size + 1) = Primitive::undefinedValue(); } void InternalClass::changeMember(Object *object, String *string, PropertyAttributes data, uint *index) |