Fix use-after-free in hashtableTwoPhasePopDelete (#1626)

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 <viktor.soderqvist@est.tech>
This commit is contained in:
Viktor Söderqvist 2025-01-27 15:45:09 +01:00 committed by GitHub
parent 88a68303c0
commit 7699a3a94a
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194

View File

@ -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.