Helper function to add u32 without overflow.

This commit is contained in:
Mike Perry 2018-04-02 07:12:15 +00:00
parent dfa6808f57
commit 0e06a9c3e7
3 changed files with 33 additions and 0 deletions

View File

@ -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)

View File

@ -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. */

View File

@ -6049,6 +6049,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)
{
@ -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),