aboutsummaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
authorErik Verbruggen <erik.verbruggen@qt.io>2018-02-13 15:20:22 +0100
committerSimon Hausmann <simon.hausmann@qt.io>2018-02-14 21:01:55 +0000
commitd19127807c193d612c6fee4f3418a8c8af9d262c (patch)
tree8e46dab79020b00bc843ed13aa608dcd69f6aa97 /src
parenta484ea0d3666b57bb49e9284ff86af3ba87ce58b (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.cpp49
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)