diff options
author | Mark Brand <mabrand@mabrand.nl> | 2012-09-25 23:50:01 +0200 |
---|---|---|
committer | The Qt Project <gerrit-noreply@qt-project.org> | 2012-10-05 03:16:12 +0200 |
commit | 5fe272f68a59724022f545ac15c2f7d758c5ea86 (patch) | |
tree | 8824c1a0c6afd0dd858473c13404c3b8f4c90d45 /src/sql | |
parent | c86ed49a7989adb3e2e3c42794e44609f12ce493 (diff) |
QSqlTableModel: fix segfault when overriding selectRow()
The STL-style iteration over the cache in submitAll() assumed the
iterator would remain valid until reaching cache.end(). This failed
to consider that virtual selectRow() might be overridden so that
it removes rows from the cache. For example, it might call select()
which would empty the cache.
The new approach checks at each iteration whether the row is
still in the cache. Using foreach here is justified by its fitness
for purpose and readability.
New test included.
Change-Id: Idee8807ede239c3ba56ff1604574c49f47385ad2
Reviewed-by: David Faure (fixes for KDE) <faure@kde.org>
Diffstat (limited to 'src/sql')
-rw-r--r-- | src/sql/models/qsqltablemodel.cpp | 23 |
1 files changed, 14 insertions, 9 deletions
diff --git a/src/sql/models/qsqltablemodel.cpp b/src/sql/models/qsqltablemodel.cpp index 95cd0d80d2..56838a4e8f 100644 --- a/src/sql/models/qsqltablemodel.cpp +++ b/src/sql/models/qsqltablemodel.cpp @@ -718,20 +718,25 @@ bool QSqlTableModel::submitAll() bool success = true; - for (QSqlTableModelPrivate::CacheMap::Iterator it = d->cache.begin(); - it != d->cache.end(); ++it) { - if (it.value().submitted()) + foreach (int row, d->cache.keys()) { + // be sure cache *still* contains the row since overriden selectRow() could have called select() + QSqlTableModelPrivate::CacheMap::iterator it = d->cache.find(row); + if (it == d->cache.end()) continue; - switch (it.value().op()) { + QSqlTableModelPrivate::ModifiedRow &mrow = it.value(); + if (mrow.submitted()) + continue; + + switch (mrow.op()) { case QSqlTableModelPrivate::Insert: - success = insertRowIntoTable(it.value().rec()); + success = insertRowIntoTable(mrow.rec()); break; case QSqlTableModelPrivate::Update: - success = updateRowInTable(it.key(), it.value().rec()); + success = updateRowInTable(row, mrow.rec()); break; case QSqlTableModelPrivate::Delete: - success = deleteRowFromTable(it.key()); + success = deleteRowFromTable(row); break; case QSqlTableModelPrivate::None: Q_ASSERT_X(false, "QSqlTableModel::submitAll()", "Invalid cache operation"); @@ -739,9 +744,9 @@ bool QSqlTableModel::submitAll() } if (success) { - it.value().setSubmitted(); + mrow.setSubmitted(); if (d->strategy != OnManualSubmit) - success = selectRow(it.key()); + success = selectRow(row); } if (!success) |