commit 0e06a9c3e76620881db95718f60441ce7de0f3c9 Author: Mike Perry mikeperry-git@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),
tor-commits@lists.torproject.org