diff options
author | Erik Verbruggen <erik.verbruggen@qt.io> | 2017-09-22 10:18:08 +0200 |
---|---|---|
committer | Erik Verbruggen <erik.verbruggen@qt.io> | 2017-09-22 09:02:20 +0000 |
commit | 163c515783877b8b0ffb8b5c1bab288addee9745 (patch) | |
tree | 7ab027a284793c253f0717c623cf5d82b62a5ae3 /src/qml/types | |
parent | 221b3f614a9c58cd5ac1aa4c36d36fb8a4cd56d0 (diff) |
Fix use-after-free when clear()ing all elements from a ListModel
Same problem as the problem with remove(), so now clear will call into
remove to do the correct thing.
See also e29ffa179e9920443a23e2fcb3f0694df32e8a68.
[ChangeLog][Qt][Qml] Fix possible use-after-free when clearing all items from a ListModel through JavaScript.
Change-Id: Ib9389d80798c4333425b4a49930b1670307d06ac
Task-number: QTBUG-59256
Reviewed-by: Simon Hausmann <simon.hausmann@qt.io>
Diffstat (limited to 'src/qml/types')
-rw-r--r-- | src/qml/types/qqmllistmodel.cpp | 66 | ||||
-rw-r--r-- | src/qml/types/qqmllistmodel_p.h | 2 | ||||
-rw-r--r-- | src/qml/types/qqmllistmodel_p_p.h | 1 |
3 files changed, 28 insertions, 41 deletions
diff --git a/src/qml/types/qqmllistmodel.cpp b/src/qml/types/qqmllistmodel.cpp index 35ee30dccf..2b4e906617 100644 --- a/src/qml/types/qqmllistmodel.cpp +++ b/src/qml/types/qqmllistmodel.cpp @@ -341,7 +341,9 @@ ListModel::ListModel(ListLayout *layout, QQmlListModel *modelCache, int uid) : m void ListModel::destroy() { - clear(); + for (const auto &destroyer : remove(0, elements.count())) + destroyer(); + m_uid = -1; m_layout = 0; if (m_modelCache && m_modelCache->m_primary == false) @@ -557,16 +559,6 @@ void ListModel::set(int elementIndex, QV4::Object *object) } } -void ListModel::clear() -{ - int elementCount = elements.count(); - for (int i=0 ; i < elementCount ; ++i) { - elements[i]->destroy(m_layout); - delete elements[i]; - } - elements.clear(); -} - QVector<std::function<void()>> ListModel::remove(int index, int count) { QVector<std::function<void()>> toDestroy; @@ -2025,18 +2017,7 @@ int QQmlListModel::count() const */ void QQmlListModel::clear() { - const int cleared = count(); - - emitItemsAboutToBeRemoved(0, cleared); - - if (m_dynamicRoles) { - qDeleteAll(m_modelObjects); - m_modelObjects.clear(); - } else { - m_listModel->clear(); - } - - emitItemsRemoved(0, cleared); + removeElements(0, count()); } /*! @@ -2060,27 +2041,32 @@ void QQmlListModel::remove(QQmlV4Function *args) return; } - emitItemsAboutToBeRemoved(index, removeCount); + removeElements(index, removeCount); + } else { + qmlWarning(this) << tr("remove: incorrect number of arguments"); + } +} - QVector<std::function<void()>> toDestroy; - if (m_dynamicRoles) { - for (int i=0 ; i < removeCount ; ++i) { - auto modelObject = m_modelObjects[index+i]; - toDestroy.append([modelObject](){ - delete modelObject; - }); - } - m_modelObjects.remove(index, removeCount); - } else { - toDestroy = m_listModel->remove(index, removeCount); - } +void QQmlListModel::removeElements(int index, int removeCount) +{ + emitItemsAboutToBeRemoved(index, removeCount); - emitItemsRemoved(index, removeCount); - for (const auto &destroyer : toDestroy) - destroyer(); + QVector<std::function<void()>> toDestroy; + if (m_dynamicRoles) { + for (int i=0 ; i < removeCount ; ++i) { + auto modelObject = m_modelObjects[index+i]; + toDestroy.append([modelObject](){ + delete modelObject; + }); + } + m_modelObjects.remove(index, removeCount); } else { - qmlWarning(this) << tr("remove: incorrect number of arguments"); + toDestroy = m_listModel->remove(index, removeCount); } + + emitItemsRemoved(index, removeCount); + for (const auto &destroyer : toDestroy) + destroyer(); } /*! diff --git a/src/qml/types/qqmllistmodel_p.h b/src/qml/types/qqmllistmodel_p.h index b750d30676..1fda703797 100644 --- a/src/qml/types/qqmllistmodel_p.h +++ b/src/qml/types/qqmllistmodel_p.h @@ -165,6 +165,8 @@ private: void emitItemsInserted(int index, int count); void emitItemsAboutToBeMoved(int from, int to, int n); void emitItemsMoved(int from, int to, int n); + + void removeElements(int index, int removeCount); }; // ### FIXME diff --git a/src/qml/types/qqmllistmodel_p_p.h b/src/qml/types/qqmllistmodel_p_p.h index 4928ad3725..10916f10db 100644 --- a/src/qml/types/qqmllistmodel_p_p.h +++ b/src/qml/types/qqmllistmodel_p_p.h @@ -366,7 +366,6 @@ public: int append(QV4::Object *object); void insert(int elementIndex, QV4::Object *object); - void clear(); Q_REQUIRED_RESULT QVector<std::function<void()>> remove(int index, int count); int appendElement(); |