summaryrefslogtreecommitdiffstats
path: root/test
diff options
context:
space:
mode:
authorPauli <pauli@openssl.org>2022-03-15 14:19:07 +1100
committerPauli <pauli@openssl.org>2022-03-30 10:10:25 +1100
commit4157a32867e6643da8daee94e836aaa18b9feed6 (patch)
treeed00f2727a856b8313d108de65940d8d527868f1 /test
parent5d3746910438fd052b44010d92ac70fea606fa9d (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.c104
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;