Details
-
Bug
-
Resolution: Done
-
P1: Critical
-
5.12.4, 5.13.0
-
Kubuntu Linux 18.04
-
-
ef7773e5664dd8278831ed4d7d24dd4fc1aaefd3
Description
If an item in a model contains an QPersistentModelIndex of that item, the program crashes on mass model item removal.
Seems the reason is that QStandardItemModelPrivate::rowsRemoved() deletes the model item (which results in deletion of the persistent index in the model) and then calls the QAbstractItemModelPrivate::rowsRemoved() which tries to access the deleted persistent index.
To reproduce, run the test program, click on the "Add items" button and then on the "Clear items" - the program should crash.
Test program
#include <QApplication> #include <QHBoxLayout> #include <QListView> #include <QMainWindow> #include <QPushButton> #include <QStandardItemModel> #include <QVBoxLayout> const int g_createCount = 100; int main(int argc, char *argv[]) { QApplication app(argc, argv); QMainWindow mainWindow; QStandardItemModel *model = new QStandardItemModel(&mainWindow); QListView *view = new QListView(); view->setModel(model); QPushButton *addButton = new QPushButton("Add items"); QPushButton *clearButton = new QPushButton("Clear items"); QVBoxLayout *buttonsLayout = new QVBoxLayout; buttonsLayout->addStretch(1); buttonsLayout->addWidget(addButton); buttonsLayout->addWidget(clearButton); buttonsLayout->addStretch(1); QHBoxLayout *mainLayout = new QHBoxLayout; mainLayout->addWidget(view); mainLayout->addLayout(buttonsLayout); QWidget *centralWidget = new QWidget; centralWidget->setLayout(mainLayout); mainWindow.setCentralWidget(centralWidget); QObject::connect(addButton, &QAbstractButton::clicked, &mainWindow, [model]() { for (int i = 0; i < g_createCount; ++i) { auto item = new QStandardItem; model->appendRow(item); QPersistentModelIndex index = model->indexFromItem(item); item->setData(QVariant::fromValue(i), Qt::DisplayRole); item->setData(QVariant::fromValue(index), Qt::UserRole + 1); } }); QObject::connect(clearButton, &QAbstractButton::clicked, &mainWindow, [model]() { model->removeRows(0, model->rowCount()); }); mainWindow.show(); return app.exec(); }
Valgrind Memcheck found invalid read/write errors for the test program, I've attached the output of one such case.
Attachments
For Gerrit Dashboard: QTBUG-78142 | ||||||
---|---|---|---|---|---|---|
# | Subject | Branch | Project | Status | CR | V |
276692,5 | Keep model index reference between rowsAboutToBeRemoved and rowsRemoved | 5.13.2 | qt/qtbase | Status: ABANDONED | 0 | 0 |
288614,3 | Doc: QPersistentModelIndex cannot be stored in a QStandardItem | 5.14 | qt/qtbase | Status: MERGED | +2 | 0 |