aboutsummaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
authorUlf Hermann <ulf.hermann@digia.com>2014-11-06 14:40:37 +0100
committerUlf Hermann <ulf.hermann@digia.com>2014-11-06 17:52:26 +0100
commita4877338826381d454dfdae74242a007b3aac9e0 (patch)
treed62e0d19b36fd463b11ea5b11cadac59375fbc74 /src
parent61dd293a145a3881c6ff4a223121f655f1f8d0bc (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.cpp35
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