[tor-commits] [tor/master] Helper function to add u32 without overflow.

nickm at torproject.org nickm at torproject.org
Mon Apr 23 00:41:55 UTC 2018


commit 0e06a9c3e76620881db95718f60441ce7de0f3c9
Author: Mike Perry <mikeperry-git at torproject.org>
Date:   Mon Apr 2 07:12:15 2018 +0000

    Helper function to add u32 without overflow.
---
 src/common/util.c    | 13 +++++++++++++
 src/common/util.h    |  2 ++
 src/test/test_util.c | 18 ++++++++++++++++++
 3 files changed, 33 insertions(+)

diff --git a/src/common/util.c b/src/common/util.c
index 041e7aee3..b14b6f397 100644
--- a/src/common/util.c
+++ b/src/common/util.c
@@ -572,6 +572,19 @@ add_laplace_noise(int64_t signal_, double random_, double delta_f,
     return signal_ + noise;
 }
 
+/* Helper: safely add two uint32_t's, capping at UINT32_MAX rather
+ * than overflow */
+uint32_t
+tor_add_u32_nowrap(uint32_t a, uint32_t b)
+{
+  /* a+b > UINT32_MAX check, without overflow */
+  if (PREDICT_UNLIKELY(a > UINT32_MAX - b)) {
+    return UINT32_MAX;
+  } else {
+    return a+b;
+  }
+}
+
 /* Helper: return greatest common divisor of a,b */
 static uint64_t
 gcd64(uint64_t a, uint64_t b)
diff --git a/src/common/util.h b/src/common/util.h
index ae27e5f01..c0d20e1b2 100644
--- a/src/common/util.h
+++ b/src/common/util.h
@@ -176,6 +176,8 @@ int n_bits_set_u8(uint8_t v);
 int64_t clamp_double_to_int64(double number);
 void simplify_fraction64(uint64_t *numer, uint64_t *denom);
 
+uint32_t tor_add_u32_nowrap(uint32_t a, uint32_t b);
+
 /* Compute the CEIL of <b>a</b> divided by <b>b</b>, for nonnegative <b>a</b>
  * and positive <b>b</b>.  Works on integer types only. Not defined if a+(b-1)
  * can overflow. */
diff --git a/src/test/test_util.c b/src/test/test_util.c
index 24b43c899..350273bf4 100644
--- a/src/test/test_util.c
+++ b/src/test/test_util.c
@@ -6050,6 +6050,23 @@ test_util_monotonic_time_add_msec(void *arg)
 }
 
 static void
+test_util_nowrap_math(void *arg)
+{
+  (void)arg;
+
+  tt_u64_op(0, OP_EQ, tor_add_u32_nowrap(0, 0));
+  tt_u64_op(1, OP_EQ, tor_add_u32_nowrap(0, 1));
+  tt_u64_op(1, OP_EQ, tor_add_u32_nowrap(1, 0));
+  tt_u64_op(4, OP_EQ, tor_add_u32_nowrap(2, 2));
+  tt_u64_op(UINT32_MAX, OP_EQ, tor_add_u32_nowrap(UINT32_MAX-1, 2));
+  tt_u64_op(UINT32_MAX, OP_EQ, tor_add_u32_nowrap(2, UINT32_MAX-1));
+  tt_u64_op(UINT32_MAX, OP_EQ, tor_add_u32_nowrap(UINT32_MAX, UINT32_MAX));
+
+ done:
+  ;
+}
+
+static void
 test_util_htonll(void *arg)
 {
   (void)arg;
@@ -6243,6 +6260,7 @@ struct testcase_t util_tests[] = {
   UTIL_TEST(listdir, 0),
   UTIL_TEST(parent_dir, 0),
   UTIL_TEST(ftruncate, 0),
+  UTIL_TEST(nowrap_math, 0),
   UTIL_TEST(num_cpus, 0),
   UTIL_TEST_WIN_ONLY(load_win_lib, 0),
   UTIL_TEST_NO_WIN(exit_status, 0),





More information about the tor-commits mailing list