diff options
author | Ulf Hermann <ulf.hermann@digia.com> | 2014-11-06 14:40:37 +0100 |
---|---|---|
committer | Ulf Hermann <ulf.hermann@digia.com> | 2014-11-06 17:52:26 +0100 |
commit | a4877338826381d454dfdae74242a007b3aac9e0 (patch) | |
tree | d62e0d19b36fd463b11ea5b11cadac59375fbc74 /src | |
parent | 61dd293a145a3881c6ff4a223121f655f1f8d0bc (diff) |
Avoid stack overflow when destroying InternalClass
If there are deep object hierarchies connected to an InternalClass the
recursive nature of the destroy() method could lead to a stack
overflow. By changing the recursion into an iteration this is avoided.
Change-Id: I6667f268a366749c2dbc5f7147882388f192a9c5
Reviewed-by: Simon Hausmann <simon.hausmann@digia.com>
Diffstat (limited to 'src')
-rw-r--r-- | src/qml/jsruntime/qv4internalclass.cpp | 35 |
1 files changed, 17 insertions, 18 deletions
diff --git a/src/qml/jsruntime/qv4internalclass.cpp b/src/qml/jsruntime/qv4internalclass.cpp index a59c3892a1..bb22e30ac1 100644 --- a/src/qml/jsruntime/qv4internalclass.cpp +++ b/src/qml/jsruntime/qv4internalclass.cpp @@ -412,25 +412,24 @@ InternalClass *InternalClass::frozen() void InternalClass::destroy() { - if (!engine) - return; - engine = 0; - - propertyTable.~PropertyHash(); - nameMap.~SharedInternalClassData<String *>(); - propertyData.~SharedInternalClassData<PropertyAttributes>(); + QList<InternalClass *> destroyStack; + destroyStack.append(this); - if (m_sealed) - m_sealed->destroy(); - - if (m_frozen) - m_frozen->destroy(); - - for (QHash<Transition, InternalClass *>::ConstIterator it = transitions.begin(), end = transitions.end(); - it != end; ++it) - it.value()->destroy(); - - transitions.clear(); + while (!destroyStack.isEmpty()) { + InternalClass *next = destroyStack.takeLast(); + if (!next->engine) + continue; + next->engine = 0; + next->propertyTable.~PropertyHash(); + next->nameMap.~SharedInternalClassData<String *>(); + next->propertyData.~SharedInternalClassData<PropertyAttributes>(); + if (next->m_sealed) + destroyStack.append(next->m_sealed); + if (next->m_frozen) + destroyStack.append(next->m_frozen); + destroyStack.append(next->transitions.values()); + next->transitions.clear(); + } } struct InternalClassPoolVisitor |