Skip to content

Commit

Permalink
Browse files Browse the repository at this point in the history
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>
  • Loading branch information
Erik Verbruggen authored and tronical committed Feb 14, 2018
1 parent a484ea0 commit d191278
Showing 1 changed file with 11 additions and 38 deletions.
49 changes: 11 additions & 38 deletions src/qml/jsruntime/qv4internalclass.cpp
Expand Up @@ -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)
Expand Down

0 comments on commit d191278

Please sign in to comment.