]> git.puffer.fish Git - matthieu/frr.git/commitdiff
lib: remove overflow arithmetic from hash stats
authorQuentin Young <qlyoung@nvidia.com>
Wed, 2 Sep 2020 20:02:55 +0000 (16:02 -0400)
committerQuentin Young <qlyoung@nvidia.com>
Wed, 2 Sep 2020 20:54:41 +0000 (16:54 -0400)
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 <qlyoung@nvidia.com>
lib/hash.c

index 7f8a237047f48d3d990c52efe957edee43fccb51..85982774ac8162c1d0c1ccdf2a9515fc44a0e303 100644 (file)
@@ -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)