Fix invalid vptr during destruction of animations
Fixes UBSAN warnings about objects used after partial destruction. Change-Id: Iceea083a77d47335ef595c0ff97b87f35f42e56f Reviewed-by: Ulf Hermann <ulf.hermann@qt.io>
parent
cf7d990a48
commit
48b707224e
|
|
@ -1067,6 +1067,8 @@ QAbstractAnimation::~QAbstractAnimation()
|
|||
if (oldState == QAbstractAnimation::Running)
|
||||
QAnimationTimer::unregisterAnimation(this);
|
||||
}
|
||||
if (d->group)
|
||||
d->group->removeAnimation(this);
|
||||
}
|
||||
|
||||
/*!
|
||||
|
|
|
|||
|
|
@ -113,6 +113,11 @@ QAnimationGroup::QAnimationGroup(QAnimationGroupPrivate &dd, QObject *parent)
|
|||
*/
|
||||
QAnimationGroup::~QAnimationGroup()
|
||||
{
|
||||
Q_D(QAnimationGroup);
|
||||
// We need to clear the animations now while we are still a valid QAnimationGroup.
|
||||
// If we wait until ~QObject() the QAbstractAnimation's pointer back to us would
|
||||
// point to a QObject, not a valid QAnimationGroup.
|
||||
d->clear(true);
|
||||
}
|
||||
|
||||
/*!
|
||||
|
|
@ -256,7 +261,7 @@ QAbstractAnimation *QAnimationGroup::takeAnimation(int index)
|
|||
void QAnimationGroup::clear()
|
||||
{
|
||||
Q_D(QAnimationGroup);
|
||||
qDeleteAll(d->animations);
|
||||
d->clear(false);
|
||||
}
|
||||
|
||||
/*!
|
||||
|
|
@ -284,6 +289,24 @@ bool QAnimationGroup::event(QEvent *event)
|
|||
return QAbstractAnimation::event(event);
|
||||
}
|
||||
|
||||
void QAnimationGroupPrivate::clear(bool onDestruction)
|
||||
{
|
||||
const QList<QAbstractAnimation *> animationsCopy = animations; // taking a copy
|
||||
animations.clear();
|
||||
// Clearing backwards so the indices doesn't change while we remove animations.
|
||||
for (int i = animationsCopy.count() - 1; i >= 0; --i) {
|
||||
QAbstractAnimation *animation = animationsCopy.at(i);
|
||||
animation->setParent(nullptr);
|
||||
QAbstractAnimationPrivate::get(animation)->group = nullptr;
|
||||
// If we are in ~QAnimationGroup() it is not safe to called the virtual
|
||||
// animationRemoved method, which can still be a method in a
|
||||
// QAnimationGroupPrivate derived class that assumes q_ptr is still
|
||||
// a valid derived class of QAnimationGroup.
|
||||
if (!onDestruction)
|
||||
animationRemoved(i, animation);
|
||||
delete animation;
|
||||
}
|
||||
}
|
||||
|
||||
void QAnimationGroupPrivate::animationRemoved(int index, QAbstractAnimation *)
|
||||
{
|
||||
|
|
|
|||
|
|
@ -73,6 +73,8 @@ public:
|
|||
virtual void animationInsertedAt(int) { }
|
||||
virtual void animationRemoved(int, QAbstractAnimation *);
|
||||
|
||||
void clear(bool onDestruction);
|
||||
|
||||
void disconnectUncontrolledAnimation(QAbstractAnimation *anim)
|
||||
{
|
||||
//0 for the signal here because we might be called from the animation destructor
|
||||
|
|
|
|||
|
|
@ -532,7 +532,8 @@ void QSequentialAnimationGroupPrivate::animationRemoved(int index, QAbstractAnim
|
|||
Q_Q(QSequentialAnimationGroup);
|
||||
QAnimationGroupPrivate::animationRemoved(index, anim);
|
||||
|
||||
Q_ASSERT(currentAnimation); // currentAnimation should always be set
|
||||
if (!currentAnimation)
|
||||
return;
|
||||
|
||||
if (actualDuration.size() > index)
|
||||
actualDuration.removeAt(index);
|
||||
|
|
|
|||
Loading…
Reference in New Issue