From a4877338826381d454dfdae74242a007b3aac9e0 Mon Sep 17 00:00:00 2001 From: Ulf Hermann Date: Thu, 6 Nov 2014 14:40:37 +0100 Subject: 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 --- src/qml/jsruntime/qv4internalclass.cpp | 35 +++++++++++++++++----------------- 1 file 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(); - propertyData.~SharedInternalClassData(); + QList destroyStack; + destroyStack.append(this); - if (m_sealed) - m_sealed->destroy(); - - if (m_frozen) - m_frozen->destroy(); - - for (QHash::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(); + next->propertyData.~SharedInternalClassData(); + 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 -- cgit v1.2.3