From e6464fdc184e4b0a4032286c8fae245dcdb03d8f Mon Sep 17 00:00:00 2001 From: Quentin Young Date: Wed, 2 Sep 2020 16:02:55 -0400 Subject: [PATCH] lib: remove overflow arithmetic from hash stats Signed values get converted to unsigned for addition, so when the value to adjust a stats variable for hash tables was negative this resulted in overflow arithmetic, which we generally don't want. Signed-off-by: Quentin Young --- lib/hash.c | 15 +++++++++++++-- 1 file changed, 13 insertions(+), 2 deletions(-) diff --git a/lib/hash.c b/lib/hash.c index 7f8a237047..85982774ac 100644 --- a/lib/hash.c +++ b/lib/hash.c @@ -77,9 +77,20 @@ void *hash_alloc_intern(void *arg) return arg; } +/* + * ssq = ssq + (new^2 - old^2) + * = ssq + ((new + old) * (new - old)) + */ #define hash_update_ssq(hz, old, new) \ - atomic_fetch_add_explicit(&hz->stats.ssq, (new + old) * (new - old), \ - memory_order_relaxed); + do { \ + int _adjust = (new + old) * (new - old); \ + if (_adjust < 0) \ + atomic_fetch_sub_explicit(&hz->stats.ssq, -_adjust, \ + memory_order_relaxed); \ + else \ + atomic_fetch_add_explicit(&hz->stats.ssq, _adjust, \ + memory_order_relaxed); \ + } while (0) /* Expand hash if the chain length exceeds the threshold. */ static void hash_expand(struct hash *hash) -- 2.39.5