aboutsummaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
authorUlf Hermann <ulf.hermann@qt.io>2021-02-05 13:18:25 +0100
committerQt Cherry-pick Bot <cherrypick_bot@qt-project.org>2021-02-05 16:21:11 +0000
commit2ba30fcc069f63153baeb38cd5c57d5639bdc26b (patch)
tree465f30e0eafce68be09dbb1c0e1e8d5cbf585c6b /src
parent81b3675a887e692dbcab33deb0a3bed96fb36b21 (diff)
QSequentialAnimationGroupJob: Protect against self-deletion
setCurrentAnimation() can indirectly delete the animation group job itself by invoking the animation controller. Use the RETURN_IF_DELETED mechanism to avoid the resulting dangling pointers. Task-number: QTBUG-90401 Change-Id: Ibd0ad21e8d3af4760604c3ff37dc46101d5f49ad Reviewed-by: Fabian Kosmale <fabian.kosmale@qt.io> (cherry picked from commit 680f28b08f65ad38c8d5498b5738231b2a2779a3) Reviewed-by: Qt Cherry-pick Bot <cherrypick_bot@qt-project.org>
Diffstat (limited to 'src')
-rw-r--r--src/qml/animations/qanimationjobutil_p.h4
-rw-r--r--src/qml/animations/qsequentialanimationgroupjob.cpp14
2 files changed, 9 insertions, 9 deletions
diff --git a/src/qml/animations/qanimationjobutil_p.h b/src/qml/animations/qanimationjobutil_p.h
index 83cf3b246f..2b7bda3123 100644
--- a/src/qml/animations/qanimationjobutil_p.h
+++ b/src/qml/animations/qanimationjobutil_p.h
@@ -70,7 +70,7 @@ struct SelfDeletable {
// \param func statements or functions that to be executed under test.
// \param action post process if p was deleted under test.
#define ACTION_IF_DELETED(p, func, action) \
-{ \
+do { \
static_assert(std::is_same<decltype((p)->m_selfDeletable), SelfDeletable>::value, "m_selfDeletable must be SelfDeletable");\
bool *prevWasDeleted = (p)->m_selfDeletable.m_wasDeleted; \
bool wasDeleted = false; \
@@ -82,7 +82,7 @@ struct SelfDeletable {
{action;} \
} \
(p)->m_selfDeletable.m_wasDeleted = prevWasDeleted; \
-}
+} while (false)
#define RETURN_IF_DELETED(func) \
ACTION_IF_DELETED(this, func, return)
diff --git a/src/qml/animations/qsequentialanimationgroupjob.cpp b/src/qml/animations/qsequentialanimationgroupjob.cpp
index dc57444b32..1d19bbf79d 100644
--- a/src/qml/animations/qsequentialanimationgroupjob.cpp
+++ b/src/qml/animations/qsequentialanimationgroupjob.cpp
@@ -338,7 +338,7 @@ void QSequentialAnimationGroupJob::uncontrolledAnimationFinished(QAbstractAnimat
if (m_direction == Forward) {
// set the current animation to be the next one
if (m_currentAnimation->nextSibling())
- setCurrentAnimation(m_currentAnimation->nextSibling());
+ RETURN_IF_DELETED(setCurrentAnimation(m_currentAnimation->nextSibling()));
for (QAbstractAnimationJob *a = animation->nextSibling(); a; a = a->nextSibling()) {
int dur = a->duration();
@@ -353,7 +353,7 @@ void QSequentialAnimationGroupJob::uncontrolledAnimationFinished(QAbstractAnimat
} else {
// set the current animation to be the previous one
if (m_currentAnimation->previousSibling())
- setCurrentAnimation(m_currentAnimation->previousSibling());
+ RETURN_IF_DELETED(setCurrentAnimation(m_currentAnimation->previousSibling()));
for (QAbstractAnimationJob *a = animation->previousSibling(); a; a = a->previousSibling()) {
int dur = a->duration();
@@ -374,12 +374,12 @@ void QSequentialAnimationGroupJob::uncontrolledAnimationFinished(QAbstractAnimat
void QSequentialAnimationGroupJob::animationInserted(QAbstractAnimationJob *anim)
{
if (m_currentAnimation == nullptr)
- setCurrentAnimation(firstChild()); // initialize the current animation
+ RETURN_IF_DELETED(setCurrentAnimation(firstChild())); // initialize the current animation
if (m_currentAnimation == anim->nextSibling()
&& m_currentAnimation->currentTime() == 0 && m_currentAnimation->currentLoop() == 0) {
//in this case we simply insert the animation before the current one has actually started
- setCurrentAnimation(anim);
+ RETURN_IF_DELETED(setCurrentAnimation(anim));
}
// TODO
@@ -398,11 +398,11 @@ void QSequentialAnimationGroupJob::animationRemoved(QAbstractAnimationJob *anim,
bool removingCurrent = anim == m_currentAnimation;
if (removingCurrent) {
if (next)
- setCurrentAnimation(next); //let's try to take the next one
+ RETURN_IF_DELETED(setCurrentAnimation(next)); //let's try to take the next one
else if (prev)
- setCurrentAnimation(prev);
+ RETURN_IF_DELETED(setCurrentAnimation(prev));
else// case all animations were removed
- setCurrentAnimation(nullptr);
+ RETURN_IF_DELETED(setCurrentAnimation(nullptr));
}
// duration of the previous animations up to the current animation