From 7699a3a94a5d3b2d5f2713893192ba87042fa030 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Viktor=20S=C3=B6derqvist?= Date: Mon, 27 Jan 2025 15:45:09 +0100 Subject: [PATCH] Fix use-after-free in hashtableTwoPhasePopDelete (#1626) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Use-after-free has been detect by address sanitizer, such as in this test run: https://github.com/valkey-io/valkey/actions/runs/12981530413/job/36200075972?pr=1620#step:5:1339 `hashtableShrinkIfNeeded` may free one of the hash tables and invalidate the variables used by the `fillBucketHole(ht, b, pos_in_bucket, table_index)` just after, causing use-after-free. Fill bucket hole first and shrink afterwards is assumed to solve the issue. (Not reproduced locally.) Signed-off-by: Viktor Söderqvist --- src/hashtable.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/hashtable.c b/src/hashtable.c index 23097eb246..6b503b637c 100644 --- a/src/hashtable.c +++ b/src/hashtable.c @@ -1518,7 +1518,6 @@ void hashtableTwoPhasePopDelete(hashtable *ht, hashtablePosition *pos) { assert(isPositionFilled(b, pos_in_bucket)); b->presence &= ~(1 << pos_in_bucket); ht->used[table_index]--; - hashtableShrinkIfNeeded(ht); hashtableResumeRehashing(ht); if (b->chained && !hashtableIsRehashingPaused(ht)) { /* Rehashing paused also means bucket chain compaction paused. It is @@ -1527,6 +1526,7 @@ void hashtableTwoPhasePopDelete(hashtable *ht, hashtablePosition *pos) { * we do the compaction in the scan and iterator code instead. */ fillBucketHole(ht, b, pos_in_bucket, table_index); } + hashtableShrinkIfNeeded(ht); } /* Initializes the state for an incremental find operation.