From f04974751d067ce29c2ce0c53748670c7f383eb5 Mon Sep 17 00:00:00 2001 From: Volker Hilsheimer Date: Thu, 6 Apr 2023 15:14:39 +0200 Subject: [PATCH] QFileSystemModel: don't emit invalid indexes A subclass of QFileSystemModel might override columnCount to return a value smalller than QFileSystemModelPrivate::NumColumns. In that case, constructing the bottomRight index for the dataChange signal would fail if we create it for column NumColumns - 1, and result in undefined behavior where the topLeft and bottomRight indices do not have the same parent. So ask for the columnCount of the parent index explicitly to construct the bottomRight index. The assert can be triggered via the "filesystemexplorer" example in qtdeclarative, which overrides columnCount to always return 1. As a drive-by name the variables correctly, bottom and top where mixed up. Pick-to: 6.5 Fixes: QTBUG-110632 Change-Id: I8a635ec733348d1eda2037c156ac0f7b09a2183d Reviewed-by: Mitch Curtis --- src/gui/itemmodels/qfilesystemmodel.cpp | 15 +++++++++++---- 1 file changed, 11 insertions(+), 4 deletions(-) diff --git a/src/gui/itemmodels/qfilesystemmodel.cpp b/src/gui/itemmodels/qfilesystemmodel.cpp index 9944f095fa7..9c5c21f3034 100644 --- a/src/gui/itemmodels/qfilesystemmodel.cpp +++ b/src/gui/itemmodels/qfilesystemmodel.cpp @@ -240,7 +240,7 @@ QModelIndex QFileSystemModel::index(int row, int column, const QModelIndex &pare */ QModelIndex QFileSystemModel::sibling(int row, int column, const QModelIndex &idx) const { - if (row == idx.row() && column < QFileSystemModelPrivate::NumColumns) { + if (row == idx.row() && column < columnCount(idx.parent())) { // cheap sibling operation: just adjust the column: return createIndex(row, column, idx.internalPointer()); } else { @@ -1995,9 +1995,16 @@ void QFileSystemModelPrivate::_q_fileSystemChanged(const QString &path, && visibleMin < parentNode->visibleChildren.size() && parentNode->visibleChildren.at(visibleMin) == min && visibleMax >= 0) { - QModelIndex bottom = q->index(translateVisibleLocation(parentNode, visibleMin), QFileSystemModelPrivate::NameColumn, parentIndex); - QModelIndex top = q->index(translateVisibleLocation(parentNode, visibleMax), QFileSystemModelPrivate::NumColumns - 1, parentIndex); - emit q->dataChanged(bottom, top); + // don't use NumColumns here, a subclass might override columnCount + const int lastColumn = q->columnCount(parentIndex) - 1; + const QModelIndex top = q->index(translateVisibleLocation(parentNode, visibleMin), + QFileSystemModelPrivate::NameColumn, parentIndex); + const QModelIndex bottom = q->index(translateVisibleLocation(parentNode, visibleMax), + lastColumn, parentIndex); + // We document that emitting dataChanged with indexes that don't have the + // same parent is undefined behavior. + Q_ASSERT(bottom.parent() == top.parent()); + emit q->dataChanged(top, bottom); } /*min = QString();