diff options
author | Pauli <pauli@openssl.org> | 2022-03-15 14:19:07 +1100 |
---|---|---|
committer | Pauli <pauli@openssl.org> | 2022-03-30 10:10:25 +1100 |
commit | 4157a32867e6643da8daee94e836aaa18b9feed6 (patch) | |
tree | ed00f2727a856b8313d108de65940d8d527868f1 /test | |
parent | 5d3746910438fd052b44010d92ac70fea606fa9d (diff) |
Add a divide rounding up safe math function.
This function takes arguments a & b and computes a / b rounding any
remainder up.
It is safe with respect to overflow and negative inputs. It's only fast for
non-negative inputs.
Reviewed-by: Matt Caswell <matt@openssl.org>
Reviewed-by: Tomas Mraz <tomas@openssl.org>
(Merged from https://github.com/openssl/openssl/pull/17884)
Diffstat (limited to 'test')
-rw-r--r-- | test/safe_math_test.c | 104 |
1 files changed, 68 insertions, 36 deletions
diff --git a/test/safe_math_test.c b/test/safe_math_test.c index da50ec816b..ae397151cd 100644 --- a/test/safe_math_test.c +++ b/test/safe_math_test.c @@ -27,28 +27,34 @@ OSSL_SAFE_MATH_UNSIGNED(size_t, size_t) static const struct { int a, b; - int sum_err, sub_err, mul_err, div_err, mod_err, neg_a_err, neg_b_err; - int abs_a_err, abs_b_err; -} test_ints[] = { - { 1, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, - { -1, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, - { 1, -3, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, - { -1, -3, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, - { INT_MAX, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0 }, - { INT_MAX, 2, 1, 0, 1, 0, 0, 0, 0, 0, 0 }, - { INT_MIN, 1, 0, 1, 0, 0, 0, 1, 0, 1, 0 }, - { 1, INT_MIN, 0, 1, 0, 0, 0, 0, 1, 0, 1 }, - { INT_MIN, 2, 0, 1, 1, 0, 0, 1, 0, 1, 0 }, - { 2, INT_MIN, 0, 1, 1, 0, 0, 0, 1, 0, 1 }, - { INT_MIN, -1, 1, 0, 1, 1, 1, 1, 0, 1, 0 }, - { INT_MAX, INT_MIN, 0, 1, 1, 0, 0, 0, 1, 0, 1 }, - { INT_MIN, INT_MAX, 0, 1, 1, 0, 0, 1, 0, 1, 0 }, - { 3, 0, 0, 0, 0, 1, 1, 0, 0, 0, 0 }, + int sum_err, sub_err, mul_err, div_err, mod_err, div_round_up_err; + int neg_a_err, neg_b_err, abs_a_err, abs_b_err; +} test_ints[] = { /* + - * / % /r -a -b |a||b| */ + { 1, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, + { -1, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, + { 1, -3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, + { -1, -3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, + { 3, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, + { -3, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, + { 2, -3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, + { -2, -3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, + { INT_MAX, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, + { INT_MAX, 2, 1, 0, 1, 0, 0, 0, 0, 0, 0, 0 }, + { INT_MAX, 4, 1, 0, 1, 0, 0, 0, 0, 0, 0, 0 }, + { INT_MAX - 3 , 4, 1, 0, 1, 0, 0, 0, 0, 0, 0, 0 }, + { INT_MIN, 1, 0, 1, 0, 0, 0, 0, 1, 0, 1, 0 }, + { 1, INT_MIN, 0, 1, 0, 0, 0, 0, 0, 1, 0, 1 }, + { INT_MIN, 2, 0, 1, 1, 0, 0, 0, 1, 0, 1, 0 }, + { 2, INT_MIN, 0, 1, 1, 0, 0, 0, 0, 1, 0, 1 }, + { INT_MIN, -1, 1, 0, 1, 1, 1, 1, 1, 0, 1, 0 }, + { INT_MAX, INT_MIN, 0, 1, 1, 0, 0, 0, 0, 1, 0, 1 }, + { INT_MIN, INT_MAX, 0, 1, 1, 0, 0, 0, 1, 0, 1, 0 }, + { 3, 0, 0, 0, 0, 1, 1, 1, 0, 0, 0, 0 }, }; static int test_int_ops(int n) { - int err, r; + int err, r, s; const int a = test_ints[n].a, b = test_ints[n].b; err = 0; @@ -82,6 +88,15 @@ static int test_int_ops(int n) goto err; err = 0; + r = safe_div_round_up_int(a, b, &err); + if (!TEST_int_eq(err, test_ints[n].div_round_up_err)) + goto err; + s = safe_mod_int(a, b, &err); + s = safe_add_int(safe_div_int(a, b, &err), s != 0, &err); + if (!err && !TEST_int_eq(r, s)) + goto err; + + err = 0; r = safe_neg_int(a, &err); if (!TEST_int_eq(err, test_ints[n].neg_a_err) || (!err && !TEST_int_eq(r, -a))) @@ -112,15 +127,17 @@ static int test_int_ops(int n) static const struct { unsigned int a, b; - int sum_err, sub_err, mul_err, div_err, mod_err; -} test_uints[] = { - { 3, 1, 0, 0, 0, 0, 0 }, - { 1, 3, 0, 1, 0, 0, 0 }, - { UINT_MAX, 1, 1, 0, 0, 0, 0 }, - { UINT_MAX, 2, 1, 0, 1, 0, 0 }, - { 1, UINT_MAX, 1, 1, 0, 0, 0 }, - { 2, UINT_MAX, 1, 1, 1, 0, 0 }, - { UINT_MAX, 0, 0, 0, 0, 1, 1 }, + int sum_err, sub_err, mul_err, div_err, mod_err, div_round_up_err; +} test_uints[] = { /* + - * / % /r */ + { 3, 1, 0, 0, 0, 0, 0, 0 }, + { 1, 3, 0, 1, 0, 0, 0, 0 }, + { UINT_MAX, 1, 1, 0, 0, 0, 0, 0 }, + { UINT_MAX, 2, 1, 0, 1, 0, 0, 0 }, + { UINT_MAX, 16, 1, 0, 1, 0, 0, 0 }, + { UINT_MAX - 13, 16, 1, 0, 1, 0, 0, 0 }, + { 1, UINT_MAX, 1, 1, 0, 0, 0, 0 }, + { 2, UINT_MAX, 1, 1, 1, 0, 0, 0 }, + { UINT_MAX, 0, 0, 0, 0, 1, 1, 1 }, }; static int test_uint_ops(int n) @@ -160,6 +177,12 @@ static int test_uint_ops(int n) goto err; err = 0; + r = safe_div_round_up_uint(a, b, &err); + if (!TEST_int_eq(err, test_uints[n].div_round_up_err) + || (!err && !TEST_uint_eq(r, a / b + (a % b != 0)))) + goto err; + + err = 0; r = safe_neg_uint(a, &err); if (!TEST_int_eq(err, a != 0) || (!err && !TEST_uint_eq(r, 0))) goto err; @@ -186,15 +209,18 @@ static int test_uint_ops(int n) static const struct { size_t a, b; - int sum_err, sub_err, mul_err, div_err, mod_err; + int sum_err, sub_err, mul_err, div_err, mod_err, div_round_up_err; } test_size_ts[] = { - { 3, 1, 0, 0, 0, 0, 0 }, - { 1, 3, 0, 1, 0, 0, 0 }, - { SIZE_MAX, 1, 1, 0, 0, 0, 0 }, - { SIZE_MAX, 2, 1, 0, 1, 0, 0 }, - { 1, SIZE_MAX, 1, 1, 0, 0, 0 }, - { 2, SIZE_MAX, 1, 1, 1, 0, 0 }, - { 11, 0, 0, 0, 0, 1, 1 }, + { 3, 1, 0, 0, 0, 0, 0, 0 }, + { 1, 3, 0, 1, 0, 0, 0, 0 }, + { 36, 8, 0, 0, 0, 0, 0, 0 }, + { SIZE_MAX, 1, 1, 0, 0, 0, 0, 0 }, + { SIZE_MAX, 2, 1, 0, 1, 0, 0, 0 }, + { SIZE_MAX, 8, 1, 0, 1, 0, 0, 0 }, + { SIZE_MAX - 3, 8, 1, 0, 1, 0, 0, 0 }, + { 1, SIZE_MAX, 1, 1, 0, 0, 0, 0 }, + { 2, SIZE_MAX, 1, 1, 1, 0, 0, 0 }, + { 11, 0, 0, 0, 0, 1, 1, 1 }, }; static int test_size_t_ops(int n) @@ -223,7 +249,7 @@ static int test_size_t_ops(int n) err = 0; r = safe_div_size_t(a, b, &err); - if (!TEST_int_eq(err, test_uints[n].div_err) + if (!TEST_int_eq(err, test_size_ts[n].div_err) || (!err && !TEST_size_t_eq(r, a / b))) goto err; @@ -234,6 +260,12 @@ static int test_size_t_ops(int n) goto err; err = 0; + r = safe_div_round_up_size_t(a, b, &err); + if (!TEST_int_eq(err, test_size_ts[n].div_round_up_err) + || (!err && !TEST_size_t_eq(r, a / b + (a % b != 0)))) + goto err; + + err = 0; r = safe_neg_size_t(a, &err); if (!TEST_int_eq(err, a != 0) || (!err && !TEST_size_t_eq(r, 0))) goto err; |