aboutsummaryrefslogtreecommitdiffstats
path: root/src/qml/qml/qqmlcontextdata.cpp
diff options
context:
space:
mode:
authorFabian Kosmale <fabian.kosmale@qt.io>2020-06-05 15:54:24 +0200
committerFabian Kosmale <fabian.kosmale@qt.io>2020-06-08 19:26:40 +0200
commita8ef2c12635db3fcd46e600d3a49baa7bcaa6225 (patch)
tree5354af2cb45caa4909ecfacbe3e87a77162a15f5 /src/qml/qml/qqmlcontextdata.cpp
parent84a687cc784bde49855073e4016172e0321ba13b (diff)
Prevent premature child destruction
QQmlContextData::emitDestruction suffers from the fact that code can delete objects while emitDestruction is ongoing. Notably, the sequence child->emitDestruction can trigger a call to a->destruction (of one of child's attached components), which then can indirectly delete both child and child->nextChild (for instance, when a StackView gets cleared). We prevent this by using QQmlRefPointer when iterating over the children, which keeps the child alive for the duration of the loop. This solves the same issue as 0c8e51705ac0bb86c4b123ecd30a11b41fd50b24 in 5.15 Fixes: QTBUG-84095 Change-Id: I486a65f791c2a52d6c5c0f188997225b6db75267 Reviewed-by: Ulf Hermann <ulf.hermann@qt.io>
Diffstat (limited to 'src/qml/qml/qqmlcontextdata.cpp')
-rw-r--r--src/qml/qml/qqmlcontextdata.cpp4
1 files changed, 2 insertions, 2 deletions
diff --git a/src/qml/qml/qqmlcontextdata.cpp b/src/qml/qml/qqmlcontextdata.cpp
index 33be23b14d..d9aea9b917 100644
--- a/src/qml/qml/qqmlcontextdata.cpp
+++ b/src/qml/qml/qqmlcontextdata.cpp
@@ -87,7 +87,7 @@ void QQmlContextData::emitDestruction()
emit attached->destruction();
}
- for (QQmlContextData *child = m_childContexts; child; child = child->m_nextChild)
+ for (QQmlRefPointer<QQmlContextData> child = m_childContexts; !child.isNull(); child = child->m_nextChild)
child->emitDestruction();
}
}
@@ -144,12 +144,12 @@ void QQmlContextData::clearContext()
QQmlContextData::~QQmlContextData()
{
Q_ASSERT(refCount() == 0);
- m_linkedContext = nullptr;
// avoid recursion
addref();
if (m_engine)
invalidate();
+ m_linkedContext = nullptr;
Q_ASSERT(refCount() == 1);
clearContext();