summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--src/corelib/tools/qhash.h5
-rw-r--r--tests/auto/corelib/tools/qhash/tst_qhash.cpp19
2 files changed, 23 insertions, 1 deletions
diff --git a/src/corelib/tools/qhash.h b/src/corelib/tools/qhash.h
index 121ffa9fde..392371ce5e 100644
--- a/src/corelib/tools/qhash.h
+++ b/src/corelib/tools/qhash.h
@@ -51,6 +51,8 @@
#include <initializer_list>
#include <functional> // for std::hash
+class tst_QHash; // for befriending
+
QT_BEGIN_NAMESPACE
struct QHashDummyValue
@@ -680,7 +682,7 @@ struct Data
}
// return correct position of the next element
- if (!spans[span].hasNode(index))
+ if (bucket == numBuckets - 1 || !spans[span].hasNode(index))
++it;
return it;
}
@@ -740,6 +742,7 @@ class QHash
using Data = QHashPrivate::Data<Node>;
friend class QSet<Key>;
friend class QMultiHash<Key, T>;
+ friend tst_QHash;
Data *d = nullptr;
diff --git a/tests/auto/corelib/tools/qhash/tst_qhash.cpp b/tests/auto/corelib/tools/qhash/tst_qhash.cpp
index d77160ba19..6ad7d15c77 100644
--- a/tests/auto/corelib/tools/qhash/tst_qhash.cpp
+++ b/tests/auto/corelib/tools/qhash/tst_qhash.cpp
@@ -42,6 +42,7 @@ class tst_QHash : public QObject
private slots:
void insert1();
void erase();
+ void erase_edge_case();
void key();
void swap();
@@ -532,6 +533,24 @@ void tst_QHash::erase()
QVERIFY(mit == h2.end());
}
+/*
+ With a specific seed we could end up in a situation where, upon deleting the
+ last entry in a QHash, the returned iterator would not point to the end()
+ iterator.
+*/
+void tst_QHash::erase_edge_case()
+{
+ QHash<int, int> h1;
+ h1.reserve(2);
+ h1.d->seed = 10230148258692185509ull;
+ h1.insert(3, 4);
+ h1.insert(5, 6);
+ QHash<int, int>::iterator it1 = h1.begin();
+ ++it1;
+ it1 = h1.erase(it1);
+ QVERIFY(it1 == h1.end());
+}
+
void tst_QHash::key()
{
{