From 7eb239d43e114c26a3fb4b78800669464d54aea8 Mon Sep 17 00:00:00 2001 From: Volker Hilsheimer Date: Wed, 28 Jun 2023 13:56:22 +0200 Subject: [PATCH] Don't crash when using unshift on a states group Amends 7e4b17943029b502cde63939a47f38ef900a9479, which implements Array.unshift by first appending nullptrs, then replacing those with the existing previous items, and then replacing the old positions (now nullptr) with the items to be prepended. This assumes that the append implementation of a list property accepts nullptr items, which QQuickStateGroup's implementation didn't. Note: QQuickStateGroupPrivate::append_transition also doesn't append a nullptr, and it is likely that other list property implementations also make append(nullptr) a no-op. Fixes: QTBUG-114858 Change-Id: Ib0459c2d12be5deb42563b5298f840d8ba641930 Reviewed-by: Qt CI Bot Reviewed-by: Ulf Hermann (cherry picked from commit f905876d6c3abda34dfd85cd40e300a31c1ebe52) Reviewed-by: Qt Cherry-pick Bot --- src/quick/util/qquickstategroup.cpp | 20 ++++++++++--------- .../data/listIgnoresNull.qml | 15 +++++++++++--- 2 files changed, 23 insertions(+), 12 deletions(-) diff --git a/src/quick/util/qquickstategroup.cpp b/src/quick/util/qquickstategroup.cpp index b4be946dc3..21f25d8e3d 100644 --- a/src/quick/util/qquickstategroup.cpp +++ b/src/quick/util/qquickstategroup.cpp @@ -96,8 +96,10 @@ QQuickStateGroup::QQuickStateGroup(QObject *parent) QQuickStateGroup::~QQuickStateGroup() { Q_D(const QQuickStateGroup); - for (int i = 0; i < d->states.size(); ++i) - d->states.at(i)->setStateGroup(nullptr); + for (int i = 0; i < d->states.size(); ++i) { + if (d->states.at(i)) + d->states.at(i)->setStateGroup(nullptr); + } if (d->nullState) d->nullState->setStateGroup(nullptr); } @@ -143,11 +145,9 @@ QQmlListProperty QQuickStateGroup::statesProperty() void QQuickStateGroupPrivate::append_state(QQmlListProperty *list, QQuickState *state) { QQuickStateGroup *_this = static_cast(list->object); - if (state) { - _this->d_func()->states.append(state); + _this->d_func()->states.append(state); + if (state) state->setStateGroup(_this); - } - } qsizetype QQuickStateGroupPrivate::count_state(QQmlListProperty *list) @@ -167,7 +167,8 @@ void QQuickStateGroupPrivate::clear_states(QQmlListProperty *list) QQuickStateGroup *_this = static_cast(list->object); _this->d_func()->setCurrentStateInternal(QString(), true); for (qsizetype i = 0; i < _this->d_func()->states.size(); ++i) { - _this->d_func()->states.at(i)->setStateGroup(nullptr); + if (_this->d_func()->states.at(i)) + _this->d_func()->states.at(i)->setStateGroup(nullptr); } _this->d_func()->states.clear(); } @@ -178,10 +179,11 @@ void QQuickStateGroupPrivate::replace_states(QQmlListProperty *list auto *d = self->d_func(); auto *oldState = d->states.at(index); if (oldState != state) { - oldState->setStateGroup(nullptr); + if (oldState) + oldState->setStateGroup(nullptr); state->setStateGroup(self); d->states.replace(index, state); - if (d->currentState == oldState->name()) + if (!oldState || d->currentState == oldState->name()) d->setCurrentStateInternal(state->name(), true); } } diff --git a/tests/auto/qml/qqmllistreference/data/listIgnoresNull.qml b/tests/auto/qml/qqmllistreference/data/listIgnoresNull.qml index 6815edb916..35c8d66dad 100644 --- a/tests/auto/qml/qqmllistreference/data/listIgnoresNull.qml +++ b/tests/auto/qml/qqmllistreference/data/listIgnoresNull.qml @@ -1,12 +1,21 @@ -import QtQml +import QtQuick 2.7 import Test -TestItem { - id: testItem +Item { + id: root + + TestItem { + id: testItem + } Component.onCompleted : { testItem.data.push(null); testItem.data.length = 5; testItem.data.unshift(null); + + var state = Qt.createQmlObject( "import QtQuick 2.7; State{ name: 'MyState' }", root, "dynamicState" ); + root.states.length = 5; + root.states.push(null); + root.states.unshift(state); } }