aboutsummaryrefslogtreecommitdiffstats
path: root/tests
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-09 12:55:39 +0000
commit604696479781c15ce3c967f30b63c53b15771dcb (patch)
treea62dfdd6da460fa844696518408fdd976e351e7a /tests
parenta1c24fe34511eb7c63e000b2607977b2f26bf323 (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 'tests')
-rw-r--r--tests/auto/qml/animation/qsequentialanimationgroupjob/tst_qsequentialanimationgroupjob.cpp42
1 files changed, 41 insertions, 1 deletions
diff --git a/tests/auto/qml/animation/qsequentialanimationgroupjob/tst_qsequentialanimationgroupjob.cpp b/tests/auto/qml/animation/qsequentialanimationgroupjob/tst_qsequentialanimationgroupjob.cpp
index 57b0905a8a..150734496e 100644
--- a/tests/auto/qml/animation/qsequentialanimationgroupjob/tst_qsequentialanimationgroupjob.cpp
+++ b/tests/auto/qml/animation/qsequentialanimationgroupjob/tst_qsequentialanimationgroupjob.cpp
@@ -68,6 +68,7 @@ private slots:
void insertAnimation();
void clear();
void pauseResume();
+ void deleteFromListener();
};
void tst_QSequentialAnimationGroupJob::initTestCase()
@@ -126,15 +127,23 @@ protected:
class StateChangeListener: public QAnimationJobChangeListener
{
public:
- virtual void animationStateChanged(QAbstractAnimationJob *, QAbstractAnimationJob::State newState, QAbstractAnimationJob::State)
+ virtual void animationStateChanged(
+ QAbstractAnimationJob *job, QAbstractAnimationJob::State newState,
+ QAbstractAnimationJob::State)
{
states << newState;
+ if (beEvil) {
+ delete job->group();
+ groupDeleted = true;
+ }
}
void clear() { states.clear(); }
int count() const { return states.count(); }
QList<QAbstractAnimationJob::State> states;
+ bool beEvil = false;
+ bool groupDeleted = false;
};
class FinishedListener: public QAnimationJobChangeListener
@@ -1644,6 +1653,37 @@ void tst_QSequentialAnimationGroupJob::uncontrolledWithLoops()
QTRY_COMPARE(group.state(), QAbstractAnimationJob::Stopped);
}
+void tst_QSequentialAnimationGroupJob::deleteFromListener()
+{
+ QSequentialAnimationGroupJob *group = new QSequentialAnimationGroupJob;
+
+ UncontrolledAnimation *uncontrolled = new UncontrolledAnimation();
+ TestAnimation *shortLoop = new TestAnimation(100);
+ UncontrolledAnimation *more = new UncontrolledAnimation();
+
+ shortLoop->setLoopCount(-1);
+
+ group->appendAnimation(uncontrolled);
+ group->appendAnimation(shortLoop);
+ group->appendAnimation(more);
+
+ StateChangeListener listener;
+ listener.beEvil = true;
+ shortLoop->addAnimationChangeListener(&listener, QAbstractAnimationJob::StateChange);
+ group->setLoopCount(2);
+
+ group->start();
+
+ QCOMPARE(group->currentLoop(), 0);
+ QCOMPARE(group->state(), QAbstractAnimationJob::Running);
+ QTRY_COMPARE(uncontrolled->state(), QAbstractAnimationJob::Running);
+
+ QVERIFY(!listener.groupDeleted);
+ uncontrolled->stop();
+
+ QTRY_VERIFY(listener.groupDeleted);
+ // It's dead, Jim.
+}
QTEST_MAIN(tst_QSequentialAnimationGroupJob)
#include "tst_qsequentialanimationgroupjob.moc"