From baa035684998616ec47bd4812fa24d25d1f5da2b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?M=C3=A5rten=20Nordheim?= Date: Tue, 12 Jan 2021 17:25:03 +0100 Subject: [PATCH] QCache: when overwriting, store the new cost instead of the delta The delta was clearly intended to be used on the total (and still is) but it also wound up getting stored in the cache, which wouldn't be a big problem unless the object was removed, in which case we could incidentally 'free up more space' than intended. Change-Id: Ib2b0f072d30da6d16a93dce60e4c5f6080c109fc Reviewed-by: Lars Knoll (cherry picked from commit d2e2d0d3a6249ccbc17ec92acb32fec9a0d71807) Reviewed-by: Qt Cherry-pick Bot --- src/corelib/tools/qcache.h | 3 ++- tests/auto/corelib/tools/qcache/tst_qcache.cpp | 14 ++++++++++++++ 2 files changed, 16 insertions(+), 1 deletion(-) diff --git a/src/corelib/tools/qcache.h b/src/corelib/tools/qcache.h index 41cf9abc467..8a341c8555b 100644 --- a/src/corelib/tools/qcache.h +++ b/src/corelib/tools/qcache.h @@ -245,8 +245,9 @@ public: auto result = d.findOrInsert(key); Node *n = result.it.node(); if (result.initialized) { - cost -= n->value.cost; + auto prevCost = n->value.cost; result.it.node()->emplace(object, cost); + cost -= prevCost; relink(key); } else { Node::createInPlace(n, key, object, cost); diff --git a/tests/auto/corelib/tools/qcache/tst_qcache.cpp b/tests/auto/corelib/tools/qcache/tst_qcache.cpp index 54cf00f9da5..da6f1bb34bf 100644 --- a/tests/auto/corelib/tools/qcache/tst_qcache.cpp +++ b/tests/auto/corelib/tools/qcache/tst_qcache.cpp @@ -49,6 +49,7 @@ private slots: void axioms_on_key_type(); void largeCache(); void internalChainOrderAfterEntryUpdate(); + void emplaceLowerCost(); }; @@ -431,5 +432,18 @@ void tst_QCache::internalChainOrderAfterEntryUpdate() QCOMPARE(cache.size(), 0); } +void tst_QCache::emplaceLowerCost() +{ + QCache cache; + cache.setMaxCost(5); + cache.insert("a", new int, 3); // insert high cost + cache.insert("a", new int, 1); // and then exchange it with a lower-cost object + QCOMPARE(cache.totalCost(), 1); + cache.remove("a"); // then remove the object + // The cache should now have a cost == 0 and be empty. + QCOMPARE(cache.totalCost(), 0); + QVERIFY(cache.isEmpty()); +} + QTEST_APPLESS_MAIN(tst_QCache) #include "tst_qcache.moc"