aboutsummaryrefslogtreecommitdiffstats
path: root/src/quick/util/qquickanimation.cpp
diff options
context:
space:
mode:
authorFabian Kosmale <fabian.kosmale@qt.io>2023-03-13 14:53:39 +0100
committerFabian Kosmale <fabian.kosmale@qt.io>2023-06-13 20:35:32 +0200
commit8a74155411d7a22bb8efa405fe59a681e47e6b45 (patch)
tree50c26f7191fb511bdb148d7d56538f5000579114 /src/quick/util/qquickanimation.cpp
parentaea823b493d0779c1019b27fc8a2203fe162f235 (diff)
PropertyAnimation: Handle targets being deleted
QQuickPropertyAnimation does not own the targets in its targets list. Thus, we need to be careful to not access deleted objects. Calling QQmlData::wasDeleted is not enoguh, as the object might be fully deleted, but we'd still have a dangling pointer to it. Fix the issue by using QPointer. A similar issue might exists for target, but there we don't normally end up with dangling references - the engine will correctly null the target. And the QPointer isNull check will avoid potentiall nullptr derefences there, too. Ideally, we would use QQmlGuard instead of QPointer, as it would have a lower overhead - however, we run into linker issues on MSVC. Fixing them is deferred to a future commit, to not block this crash fix. Fixes: QTBUG-100392 Pick-to: 6.5 6.6 6.2 Change-Id: If084e2e0f22d50dbee8bf5aedfa2e749e79fc105 Reviewed-by: Qt CI Bot <qt_ci_bot@qt-project.org> Reviewed-by: Mitch Curtis <mitch.curtis@qt.io>
Diffstat (limited to 'src/quick/util/qquickanimation.cpp')
-rw-r--r--src/quick/util/qquickanimation.cpp41
1 files changed, 38 insertions, 3 deletions
diff --git a/src/quick/util/qquickanimation.cpp b/src/quick/util/qquickanimation.cpp
index 113fcf50f0..5aa2eaa1f4 100644
--- a/src/quick/util/qquickanimation.cpp
+++ b/src/quick/util/qquickanimation.cpp
@@ -2649,7 +2649,38 @@ void QQuickPropertyAnimation::setProperties(const QString &prop)
QQmlListProperty<QObject> QQuickPropertyAnimation::targets()
{
Q_D(QQuickPropertyAnimation);
- return QQmlListProperty<QObject>(this, &(d->targets));
+ using ListPtr = QList<QPointer<QObject>> *;
+ using LP = QQmlListProperty<QObject>;
+ LP::AppendFunction appendFn = [](LP *prop, QObject *value)
+ {
+ static_cast<ListPtr>(prop->data)->append(value);
+ };
+ LP::CountFunction countFn = [](LP *prop)
+ {
+ return static_cast<ListPtr>(prop->data)->size();
+ };
+
+ LP::AtFunction atFn = [](LP *prop, qsizetype index) -> QObject *
+ {
+ return static_cast<ListPtr>(prop->data)->at(index);
+ };
+
+ LP::ClearFunction clearFN = [](LP *prop)
+ {
+ return static_cast<ListPtr>(prop->data)->clear();
+ };
+
+ LP::ReplaceFunction replaceFn = [](LP *prop, qsizetype index, QObject *value)
+ {
+ static_cast<ListPtr>(prop->data)->replace(index, value);
+ };
+
+ LP::RemoveLastFunction removeLastFn = [](LP *prop)
+ {
+ static_cast<ListPtr>(prop->data)->removeLast();
+ };
+
+ return QQmlListProperty<QObject>(this, &(d->targets), appendFn, countFn, atFn, clearFN, replaceFn, removeLastFn);
}
/*!
@@ -2721,7 +2752,7 @@ QQuickStateActions QQuickPropertyAnimation::createTransitionActions(QQuickStateA
if (!d->propertyName.isEmpty())
props << d->propertyName;
- QList<QObject*> targets = d->targets;
+ QList<QPointer<QObject>> targets = d->targets;
if (d->target)
targets.append(d->target);
@@ -2750,10 +2781,14 @@ QQuickStateActions QQuickPropertyAnimation::createTransitionActions(QQuickStateA
for (int i = 0; i < props.size(); ++i) {
for (int j = 0; j < targets.size(); ++j) {
+ const auto& guarded = targets.at(j);
+ if (guarded.isNull())
+ continue;
+ QObject *target = guarded.get();
QQuickStateAction myAction;
QString errorMessage;
const QString &propertyName = props.at(i);
- myAction.property = d->createProperty(targets.at(j), propertyName, this, &errorMessage);
+ myAction.property = d->createProperty(target, propertyName, this, &errorMessage);
if (myAction.property.isValid()) {
if (usingDefaultProperties)
successfullyCreatedDefaultProperty = true;