summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorIvan Solovev <ivan.solovev@qt.io>2022-03-30 17:09:32 +0200
committerQt Cherry-pick Bot <cherrypick_bot@qt-project.org>2022-04-06 14:47:14 +0000
commitc097807ebfb24f0622fe28df7a219c20455b21b4 (patch)
tree81e9ab798bbc7cd403c537845485e1e5cbe67f3b
parent772051ea67a7fe9f460f911e73dc41f4ccbd9162 (diff)
Q[Multi]Hash::reserve(): do nothing if desired size is less than current
Calling Q[Multi]Hash::reserve(n) when n is much smaller than the current amount of elements in the hash, could result in an infinite loop, because at some point the algorithm could not find a free bucket for the element. Fixing it by returning early if the new desired capacity is less than current. Fixes: QTBUG-102067 Change-Id: I38ef0b2168c4e2a317eedf91b2155b1fdffb1c27 Reviewed-by: MÃ¥rten Nordheim <marten.nordheim@qt.io> Reviewed-by: Thiago Macieira <thiago.macieira@intel.com> (cherry picked from commit d11941db41f00525f907417bbcd6ac5ee30d8485) Reviewed-by: Qt Cherry-pick Bot <cherrypick_bot@qt-project.org>
-rw-r--r--src/corelib/tools/qhash.h6
-rw-r--r--tests/auto/corelib/tools/qhash/tst_qhash.cpp31
2 files changed, 37 insertions, 0 deletions
diff --git a/src/corelib/tools/qhash.h b/src/corelib/tools/qhash.h
index 3190a2e34e..9b46fc5c0f 100644
--- a/src/corelib/tools/qhash.h
+++ b/src/corelib/tools/qhash.h
@@ -857,6 +857,9 @@ public:
inline qsizetype capacity() const noexcept { return d ? qsizetype(d->numBuckets >> 1) : 0; }
void reserve(qsizetype size)
{
+ // reserve(0) is used in squeeze()
+ if (size && (this->capacity() >= size))
+ return;
if (isDetached())
d->rehash(size);
else
@@ -1374,6 +1377,9 @@ public:
inline qsizetype capacity() const noexcept { return d ? qsizetype(d->numBuckets >> 1) : 0; }
void reserve(qsizetype size)
{
+ // reserve(0) is used in squeeze()
+ if (size && (this->capacity() >= size))
+ return;
if (isDetached())
d->rehash(size);
else
diff --git a/tests/auto/corelib/tools/qhash/tst_qhash.cpp b/tests/auto/corelib/tools/qhash/tst_qhash.cpp
index 50c2b0d84e..9982c08392 100644
--- a/tests/auto/corelib/tools/qhash/tst_qhash.cpp
+++ b/tests/auto/corelib/tools/qhash/tst_qhash.cpp
@@ -97,6 +97,7 @@ private slots:
void fineTuningInEmptyHash();
void reserveShared();
+ void reserveLessThanCurrentAmount();
void QTBUG98265();
@@ -2640,6 +2641,36 @@ void tst_QHash::reserveShared()
QCOMPARE(hash.capacity(), oldCap);
}
+void tst_QHash::reserveLessThanCurrentAmount()
+{
+ {
+ QHash<int, int> hash;
+ for (int i = 0; i < 1000; ++i)
+ hash.insert(i, i * 10);
+
+ // This used to hang in an infinite loop: QTBUG-102067
+ hash.reserve(1);
+
+ // Make sure that hash still has all elements
+ for (int i = 0; i < 1000; ++i)
+ QCOMPARE(hash.value(i), i * 10);
+ }
+ {
+ QMultiHash<int, int> hash;
+ for (int i = 0; i < 1000; ++i) {
+ hash.insert(i, i * 10);
+ hash.insert(i, i * 10 + 1);
+ }
+
+ // This used to hang in infinite loop: QTBUG-102067
+ hash.reserve(1);
+
+ // Make sure that hash still has all elements
+ for (int i = 0; i < 1000; ++i)
+ QCOMPARE(hash.values(i), QList<int>() << i * 10 + 1 << i * 10);
+ }
+}
+
void tst_QHash::QTBUG98265()
{
QMultiHash<QUuid, QByteArray> a;