From c284c800bfe84c4d5f61a2291c436403119d2ce3 Mon Sep 17 00:00:00 2001 From: Paul Driver Date: Wed, 15 Nov 2017 10:00:11 -0800 Subject: [PATCH] Update arm_u state correctly in _ch_buck_trim Previously, trimming the penultimate value from a hash bucket would leave arm_u in an inconsistent state: mug_w would be pointing at a key-value pair in a node, but arm_u.buc_o and arm_u.inx_w were not updated to reflect this. Correspondingly, a rare edge case could occur where said key-value pair would not be marked cold (due to buc_o), which is a semantic error. --- noun/hashtable.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/noun/hashtable.c b/noun/hashtable.c index 14316b2e8..410119f7f 100644 --- a/noun/hashtable.c +++ b/noun/hashtable.c @@ -281,10 +281,12 @@ _ch_trim_buck(u3h_root* har_u, u3h_slot* sot_w) u3h_slot* tos_w = &(hab_u->sot_w[har_u->arm_u.inx_w]); if ( c3y == _ch_trim_slot(har_u, tos_w, 0, 0) ) { if ( 2 == len_w ) { - // 2 things in bucket: pick the other and promote - // + // 2 things in bucket: debucketize to key-value pair, the next + // run will point at this pair (same mug_w, no longer in bucket) *sot_w = hab_u->sot_w[ (0 == har_u->arm_u.inx_w) ? 1 : 0 ]; u3a_wfree(hab_u); + har_u->arm_u.inx_w = 0; + har_u->arm_u.buc_o = c3n; } else { // shrink bucket in place; don't reallocate, we could be low on memory