summaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
authorStephen Kelly <stephen.kelly@kdab.com>2012-08-06 16:45:06 +0200
committerQt by Nokia <qt-info@nokia.com>2012-08-07 11:15:55 +0200
commitb84e180263d0da3d1e6967fcf759225a778ea6ea (patch)
tree8635817a586ee10c7b6f839d17f9800f977ed185 /src
parentb37849a5f54d7d3e66adb4430daa2cbd7b366f13 (diff)
Avoid crashes when invalidating a proxy model filter.
Task-number: QTBUG-26107 Change-Id: I2df7ae6402136570c8469d3251edae6ca8290f1f Reviewed-by: Olivier Goffart <ogoffart@woboq.com>
Diffstat (limited to 'src')
-rw-r--r--src/corelib/itemmodels/qsortfilterproxymodel.cpp13
1 files changed, 10 insertions, 3 deletions
diff --git a/src/corelib/itemmodels/qsortfilterproxymodel.cpp b/src/corelib/itemmodels/qsortfilterproxymodel.cpp
index 875bb81967..fb84dce861 100644
--- a/src/corelib/itemmodels/qsortfilterproxymodel.cpp
+++ b/src/corelib/itemmodels/qsortfilterproxymodel.cpp
@@ -1049,12 +1049,19 @@ void QSortFilterProxyModelPrivate::filter_changed(const QModelIndex &source_pare
Mapping *m = it.value();
QSet<int> rows_removed = handle_filter_changed(m->proxy_rows, m->source_rows, source_parent, Qt::Vertical);
QSet<int> columns_removed = handle_filter_changed(m->proxy_columns, m->source_columns, source_parent, Qt::Horizontal);
- QVector<QModelIndex>::iterator it2 = m->mapped_children.end();
- while (it2 != m->mapped_children.begin()) {
+
+ // We need to iterate over a copy of m->mapped_children because otherwise it may be changed by other code, invalidating
+ // the iterator it2.
+ // The m->mapped_children vector can be appended to when this function recurses for child indexes.
+ // The handle_filter_changed implementation can cause source_parent.parent() to be called, which will create
+ // a mapping (and do appending) while we are invalidating the filter.
+ QVector<QModelIndex> mappedChildren = m->mapped_children;
+ QVector<QModelIndex>::iterator it2 = mappedChildren.end();
+ while (it2 != mappedChildren.begin()) {
--it2;
const QModelIndex source_child_index = *it2;
if (rows_removed.contains(source_child_index.row()) || columns_removed.contains(source_child_index.column())) {
- it2 = m->mapped_children.erase(it2);
+ it2 = mappedChildren.erase(it2);
remove_from_mapping(source_child_index);
} else {
filter_changed(source_child_index);