1*e7be843bSPierre Pronchery /*
2*e7be843bSPierre Pronchery * Copyright 2021-2024 The OpenSSL Project Authors. All Rights Reserved.
3*e7be843bSPierre Pronchery *
4*e7be843bSPierre Pronchery * Licensed under the Apache License 2.0 (the "License"). You may not use
5*e7be843bSPierre Pronchery * this file except in compliance with the License. You can obtain a copy
6*e7be843bSPierre Pronchery * in the file LICENSE in the source distribution or at
7*e7be843bSPierre Pronchery * https://www.openssl.org/source/license.html
8*e7be843bSPierre Pronchery */
9*e7be843bSPierre Pronchery
10*e7be843bSPierre Pronchery #include <stdio.h>
11*e7be843bSPierre Pronchery #include <stdlib.h>
12*e7be843bSPierre Pronchery
13*e7be843bSPierre Pronchery /*
14*e7be843bSPierre Pronchery * Uncomment this if the fallback non-builtin overflow checking is to
15*e7be843bSPierre Pronchery * be tested.
16*e7be843bSPierre Pronchery */
17*e7be843bSPierre Pronchery /*#define OPENSSL_NO_BUILTIN_OVERFLOW_CHECKING*/
18*e7be843bSPierre Pronchery
19*e7be843bSPierre Pronchery #include "internal/nelem.h"
20*e7be843bSPierre Pronchery #include "internal/safe_math.h"
21*e7be843bSPierre Pronchery #include "testutil.h"
22*e7be843bSPierre Pronchery
23*e7be843bSPierre Pronchery /* Create the safe math instances we're interested in */
24*e7be843bSPierre Pronchery OSSL_SAFE_MATH_SIGNED(int, int)
25*e7be843bSPierre Pronchery OSSL_SAFE_MATH_UNSIGNED(uint, unsigned int)
26*e7be843bSPierre Pronchery OSSL_SAFE_MATH_UNSIGNED(size_t, size_t)
27*e7be843bSPierre Pronchery
28*e7be843bSPierre Pronchery static const struct {
29*e7be843bSPierre Pronchery int a, b;
30*e7be843bSPierre Pronchery int sum_err, sub_err, mul_err, div_err, mod_err, div_round_up_err;
31*e7be843bSPierre Pronchery int neg_a_err, neg_b_err, abs_a_err, abs_b_err;
32*e7be843bSPierre Pronchery } test_ints[] = { /* + - * / % /r -a -b |a||b| */
33*e7be843bSPierre Pronchery { 1, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 },
34*e7be843bSPierre Pronchery { -1, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 },
35*e7be843bSPierre Pronchery { 1, -3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 },
36*e7be843bSPierre Pronchery { -1, -3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 },
37*e7be843bSPierre Pronchery { 3, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 },
38*e7be843bSPierre Pronchery { -3, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 },
39*e7be843bSPierre Pronchery { 2, -3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 },
40*e7be843bSPierre Pronchery { -2, -3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 },
41*e7be843bSPierre Pronchery { INT_MAX, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0 },
42*e7be843bSPierre Pronchery { INT_MAX, 2, 1, 0, 1, 0, 0, 0, 0, 0, 0, 0 },
43*e7be843bSPierre Pronchery { INT_MAX, 4, 1, 0, 1, 0, 0, 0, 0, 0, 0, 0 },
44*e7be843bSPierre Pronchery { INT_MAX - 3 , 4, 1, 0, 1, 0, 0, 0, 0, 0, 0, 0 },
45*e7be843bSPierre Pronchery { INT_MIN, 1, 0, 1, 0, 0, 0, 0, 1, 0, 1, 0 },
46*e7be843bSPierre Pronchery { 1, INT_MIN, 0, 1, 0, 0, 0, 0, 0, 1, 0, 1 },
47*e7be843bSPierre Pronchery { INT_MIN, 2, 0, 1, 1, 0, 0, 0, 1, 0, 1, 0 },
48*e7be843bSPierre Pronchery { 2, INT_MIN, 0, 1, 1, 0, 0, 0, 0, 1, 0, 1 },
49*e7be843bSPierre Pronchery { INT_MIN, -1, 1, 0, 1, 1, 1, 1, 1, 0, 1, 0 },
50*e7be843bSPierre Pronchery { INT_MAX, INT_MIN, 0, 1, 1, 0, 0, 0, 0, 1, 0, 1 },
51*e7be843bSPierre Pronchery { INT_MIN, INT_MAX, 0, 1, 1, 0, 0, 0, 1, 0, 1, 0 },
52*e7be843bSPierre Pronchery { 3, 0, 0, 0, 0, 1, 1, 1, 0, 0, 0, 0 },
53*e7be843bSPierre Pronchery };
54*e7be843bSPierre Pronchery
test_int_ops(int n)55*e7be843bSPierre Pronchery static int test_int_ops(int n)
56*e7be843bSPierre Pronchery {
57*e7be843bSPierre Pronchery int err, r, s;
58*e7be843bSPierre Pronchery const int a = test_ints[n].a, b = test_ints[n].b;
59*e7be843bSPierre Pronchery
60*e7be843bSPierre Pronchery err = 0;
61*e7be843bSPierre Pronchery r = safe_add_int(a, b, &err);
62*e7be843bSPierre Pronchery if (!TEST_int_eq(err, test_ints[n].sum_err)
63*e7be843bSPierre Pronchery || (!err && !TEST_int_eq(r, a + b)))
64*e7be843bSPierre Pronchery goto err;
65*e7be843bSPierre Pronchery
66*e7be843bSPierre Pronchery err = 0;
67*e7be843bSPierre Pronchery r = safe_sub_int(a, b, &err);
68*e7be843bSPierre Pronchery if (!TEST_int_eq(err, test_ints[n].sub_err)
69*e7be843bSPierre Pronchery || (!err && !TEST_int_eq(r, a - b)))
70*e7be843bSPierre Pronchery goto err;
71*e7be843bSPierre Pronchery
72*e7be843bSPierre Pronchery err = 0;
73*e7be843bSPierre Pronchery r = safe_mul_int(a, b, &err);
74*e7be843bSPierre Pronchery if (!TEST_int_eq(err, test_ints[n].mul_err)
75*e7be843bSPierre Pronchery || (!err && !TEST_int_eq(r, a * b)))
76*e7be843bSPierre Pronchery goto err;
77*e7be843bSPierre Pronchery
78*e7be843bSPierre Pronchery err = 0;
79*e7be843bSPierre Pronchery r = safe_div_int(a, b, &err);
80*e7be843bSPierre Pronchery if (!TEST_int_eq(err, test_ints[n].div_err)
81*e7be843bSPierre Pronchery || (!err && !TEST_int_eq(r, a / b)))
82*e7be843bSPierre Pronchery goto err;
83*e7be843bSPierre Pronchery
84*e7be843bSPierre Pronchery err = 0;
85*e7be843bSPierre Pronchery r = safe_mod_int(a, b, &err);
86*e7be843bSPierre Pronchery if (!TEST_int_eq(err, test_ints[n].mod_err)
87*e7be843bSPierre Pronchery || (!err && !TEST_int_eq(r, a % b)))
88*e7be843bSPierre Pronchery goto err;
89*e7be843bSPierre Pronchery
90*e7be843bSPierre Pronchery err = 0;
91*e7be843bSPierre Pronchery r = safe_div_round_up_int(a, b, &err);
92*e7be843bSPierre Pronchery if (!TEST_int_eq(err, test_ints[n].div_round_up_err))
93*e7be843bSPierre Pronchery goto err;
94*e7be843bSPierre Pronchery s = safe_mod_int(a, b, &err);
95*e7be843bSPierre Pronchery s = safe_add_int(safe_div_int(a, b, &err), s != 0, &err);
96*e7be843bSPierre Pronchery if (!err && !TEST_int_eq(r, s))
97*e7be843bSPierre Pronchery goto err;
98*e7be843bSPierre Pronchery
99*e7be843bSPierre Pronchery err = 0;
100*e7be843bSPierre Pronchery r = safe_neg_int(a, &err);
101*e7be843bSPierre Pronchery if (!TEST_int_eq(err, test_ints[n].neg_a_err)
102*e7be843bSPierre Pronchery || (!err && !TEST_int_eq(r, -a)))
103*e7be843bSPierre Pronchery goto err;
104*e7be843bSPierre Pronchery
105*e7be843bSPierre Pronchery err = 0;
106*e7be843bSPierre Pronchery r = safe_neg_int(b, &err);
107*e7be843bSPierre Pronchery if (!TEST_int_eq(err, test_ints[n].neg_b_err)
108*e7be843bSPierre Pronchery || (!err && !TEST_int_eq(r, -b)))
109*e7be843bSPierre Pronchery goto err;
110*e7be843bSPierre Pronchery
111*e7be843bSPierre Pronchery err = 0;
112*e7be843bSPierre Pronchery r = safe_abs_int(a, &err);
113*e7be843bSPierre Pronchery if (!TEST_int_eq(err, test_ints[n].abs_a_err)
114*e7be843bSPierre Pronchery || (!err && !TEST_int_eq(r, a < 0 ? -a : a)))
115*e7be843bSPierre Pronchery goto err;
116*e7be843bSPierre Pronchery
117*e7be843bSPierre Pronchery err = 0;
118*e7be843bSPierre Pronchery r = safe_abs_int(b, &err);
119*e7be843bSPierre Pronchery if (!TEST_int_eq(err, test_ints[n].abs_b_err)
120*e7be843bSPierre Pronchery || (!err && !TEST_int_eq(r, b < 0 ? -b : b)))
121*e7be843bSPierre Pronchery goto err;
122*e7be843bSPierre Pronchery return 1;
123*e7be843bSPierre Pronchery err:
124*e7be843bSPierre Pronchery TEST_info("a = %d b = %d r = %d err = %d", a, b, r, err);
125*e7be843bSPierre Pronchery return 0;
126*e7be843bSPierre Pronchery }
127*e7be843bSPierre Pronchery
128*e7be843bSPierre Pronchery static const struct {
129*e7be843bSPierre Pronchery unsigned int a, b;
130*e7be843bSPierre Pronchery int sum_err, sub_err, mul_err, div_err, mod_err, div_round_up_err;
131*e7be843bSPierre Pronchery } test_uints[] = { /* + - * / % /r */
132*e7be843bSPierre Pronchery { 3, 1, 0, 0, 0, 0, 0, 0 },
133*e7be843bSPierre Pronchery { 1, 3, 0, 1, 0, 0, 0, 0 },
134*e7be843bSPierre Pronchery { UINT_MAX, 1, 1, 0, 0, 0, 0, 0 },
135*e7be843bSPierre Pronchery { UINT_MAX, 2, 1, 0, 1, 0, 0, 0 },
136*e7be843bSPierre Pronchery { UINT_MAX, 16, 1, 0, 1, 0, 0, 0 },
137*e7be843bSPierre Pronchery { UINT_MAX - 13, 16, 1, 0, 1, 0, 0, 0 },
138*e7be843bSPierre Pronchery { 1, UINT_MAX, 1, 1, 0, 0, 0, 0 },
139*e7be843bSPierre Pronchery { 2, UINT_MAX, 1, 1, 1, 0, 0, 0 },
140*e7be843bSPierre Pronchery { UINT_MAX, 0, 0, 0, 0, 1, 1, 1 },
141*e7be843bSPierre Pronchery };
142*e7be843bSPierre Pronchery
test_uint_ops(int n)143*e7be843bSPierre Pronchery static int test_uint_ops(int n)
144*e7be843bSPierre Pronchery {
145*e7be843bSPierre Pronchery int err;
146*e7be843bSPierre Pronchery unsigned int r;
147*e7be843bSPierre Pronchery const unsigned int a = test_uints[n].a, b = test_uints[n].b;
148*e7be843bSPierre Pronchery
149*e7be843bSPierre Pronchery err = 0;
150*e7be843bSPierre Pronchery r = safe_add_uint(a, b, &err);
151*e7be843bSPierre Pronchery if (!TEST_int_eq(err, test_uints[n].sum_err)
152*e7be843bSPierre Pronchery || (!err && !TEST_uint_eq(r, a + b)))
153*e7be843bSPierre Pronchery goto err;
154*e7be843bSPierre Pronchery
155*e7be843bSPierre Pronchery err = 0;
156*e7be843bSPierre Pronchery r = safe_sub_uint(a, b, &err);
157*e7be843bSPierre Pronchery if (!TEST_int_eq(err, test_uints[n].sub_err)
158*e7be843bSPierre Pronchery || (!err && !TEST_uint_eq(r, a - b)))
159*e7be843bSPierre Pronchery goto err;
160*e7be843bSPierre Pronchery
161*e7be843bSPierre Pronchery err = 0;
162*e7be843bSPierre Pronchery r = safe_mul_uint(a, b, &err);
163*e7be843bSPierre Pronchery if (!TEST_int_eq(err, test_uints[n].mul_err)
164*e7be843bSPierre Pronchery || (!err && !TEST_uint_eq(r, a * b)))
165*e7be843bSPierre Pronchery goto err;
166*e7be843bSPierre Pronchery
167*e7be843bSPierre Pronchery err = 0;
168*e7be843bSPierre Pronchery r = safe_div_uint(a, b, &err);
169*e7be843bSPierre Pronchery if (!TEST_int_eq(err, test_uints[n].div_err)
170*e7be843bSPierre Pronchery || (!err && !TEST_uint_eq(r, a / b)))
171*e7be843bSPierre Pronchery goto err;
172*e7be843bSPierre Pronchery
173*e7be843bSPierre Pronchery err = 0;
174*e7be843bSPierre Pronchery r = safe_mod_uint(a, b, &err);
175*e7be843bSPierre Pronchery if (!TEST_int_eq(err, test_uints[n].mod_err)
176*e7be843bSPierre Pronchery || (!err && !TEST_uint_eq(r, a % b)))
177*e7be843bSPierre Pronchery goto err;
178*e7be843bSPierre Pronchery
179*e7be843bSPierre Pronchery err = 0;
180*e7be843bSPierre Pronchery r = safe_div_round_up_uint(a, b, &err);
181*e7be843bSPierre Pronchery if (!TEST_int_eq(err, test_uints[n].div_round_up_err)
182*e7be843bSPierre Pronchery || (!err && !TEST_uint_eq(r, a / b + (a % b != 0))))
183*e7be843bSPierre Pronchery goto err;
184*e7be843bSPierre Pronchery
185*e7be843bSPierre Pronchery err = 0;
186*e7be843bSPierre Pronchery r = safe_neg_uint(a, &err);
187*e7be843bSPierre Pronchery if (!TEST_int_eq(err, a != 0) || (!err && !TEST_uint_eq(r, 0)))
188*e7be843bSPierre Pronchery goto err;
189*e7be843bSPierre Pronchery
190*e7be843bSPierre Pronchery err = 0;
191*e7be843bSPierre Pronchery r = safe_neg_uint(b, &err);
192*e7be843bSPierre Pronchery if (!TEST_int_eq(err, b != 0) || (!err && !TEST_uint_eq(r, 0)))
193*e7be843bSPierre Pronchery goto err;
194*e7be843bSPierre Pronchery
195*e7be843bSPierre Pronchery err = 0;
196*e7be843bSPierre Pronchery r = safe_abs_uint(a, &err);
197*e7be843bSPierre Pronchery if (!TEST_int_eq(err, 0) || !TEST_uint_eq(r, a))
198*e7be843bSPierre Pronchery goto err;
199*e7be843bSPierre Pronchery
200*e7be843bSPierre Pronchery err = 0;
201*e7be843bSPierre Pronchery r = safe_abs_uint(b, &err);
202*e7be843bSPierre Pronchery if (!TEST_int_eq(err, 0) || !TEST_uint_eq(r, b))
203*e7be843bSPierre Pronchery goto err;
204*e7be843bSPierre Pronchery return 1;
205*e7be843bSPierre Pronchery err:
206*e7be843bSPierre Pronchery TEST_info("a = %u b = %u r = %u err = %d", a, b, r, err);
207*e7be843bSPierre Pronchery return 0;
208*e7be843bSPierre Pronchery }
209*e7be843bSPierre Pronchery
210*e7be843bSPierre Pronchery static const struct {
211*e7be843bSPierre Pronchery size_t a, b;
212*e7be843bSPierre Pronchery int sum_err, sub_err, mul_err, div_err, mod_err, div_round_up_err;
213*e7be843bSPierre Pronchery } test_size_ts[] = {
214*e7be843bSPierre Pronchery { 3, 1, 0, 0, 0, 0, 0, 0 },
215*e7be843bSPierre Pronchery { 1, 3, 0, 1, 0, 0, 0, 0 },
216*e7be843bSPierre Pronchery { 36, 8, 0, 0, 0, 0, 0, 0 },
217*e7be843bSPierre Pronchery { SIZE_MAX, 1, 1, 0, 0, 0, 0, 0 },
218*e7be843bSPierre Pronchery { SIZE_MAX, 2, 1, 0, 1, 0, 0, 0 },
219*e7be843bSPierre Pronchery { SIZE_MAX, 8, 1, 0, 1, 0, 0, 0 },
220*e7be843bSPierre Pronchery { SIZE_MAX - 3, 8, 1, 0, 1, 0, 0, 0 },
221*e7be843bSPierre Pronchery { 1, SIZE_MAX, 1, 1, 0, 0, 0, 0 },
222*e7be843bSPierre Pronchery { 2, SIZE_MAX, 1, 1, 1, 0, 0, 0 },
223*e7be843bSPierre Pronchery { 11, 0, 0, 0, 0, 1, 1, 1 },
224*e7be843bSPierre Pronchery };
225*e7be843bSPierre Pronchery
test_size_t_ops(int n)226*e7be843bSPierre Pronchery static int test_size_t_ops(int n)
227*e7be843bSPierre Pronchery {
228*e7be843bSPierre Pronchery int err;
229*e7be843bSPierre Pronchery size_t r;
230*e7be843bSPierre Pronchery const size_t a = test_size_ts[n].a, b = test_size_ts[n].b;
231*e7be843bSPierre Pronchery
232*e7be843bSPierre Pronchery err = 0;
233*e7be843bSPierre Pronchery r = safe_add_size_t(a, b, &err);
234*e7be843bSPierre Pronchery if (!TEST_int_eq(err, test_size_ts[n].sum_err)
235*e7be843bSPierre Pronchery || (!err && !TEST_size_t_eq(r, a + b)))
236*e7be843bSPierre Pronchery goto err;
237*e7be843bSPierre Pronchery
238*e7be843bSPierre Pronchery err = 0;
239*e7be843bSPierre Pronchery r = safe_sub_size_t(a, b, &err);
240*e7be843bSPierre Pronchery if (!TEST_int_eq(err, test_size_ts[n].sub_err)
241*e7be843bSPierre Pronchery || (!err && !TEST_size_t_eq(r, a - b)))
242*e7be843bSPierre Pronchery goto err;
243*e7be843bSPierre Pronchery
244*e7be843bSPierre Pronchery err = 0;
245*e7be843bSPierre Pronchery r = safe_mul_size_t(a, b, &err);
246*e7be843bSPierre Pronchery if (!TEST_int_eq(err, test_size_ts[n].mul_err)
247*e7be843bSPierre Pronchery || (!err && !TEST_size_t_eq(r, a * b)))
248*e7be843bSPierre Pronchery goto err;
249*e7be843bSPierre Pronchery
250*e7be843bSPierre Pronchery err = 0;
251*e7be843bSPierre Pronchery r = safe_div_size_t(a, b, &err);
252*e7be843bSPierre Pronchery if (!TEST_int_eq(err, test_size_ts[n].div_err)
253*e7be843bSPierre Pronchery || (!err && !TEST_size_t_eq(r, a / b)))
254*e7be843bSPierre Pronchery goto err;
255*e7be843bSPierre Pronchery
256*e7be843bSPierre Pronchery err = 0;
257*e7be843bSPierre Pronchery r = safe_mod_size_t(a, b, &err);
258*e7be843bSPierre Pronchery if (!TEST_int_eq(err, test_size_ts[n].mod_err)
259*e7be843bSPierre Pronchery || (!err && !TEST_size_t_eq(r, a % b)))
260*e7be843bSPierre Pronchery goto err;
261*e7be843bSPierre Pronchery
262*e7be843bSPierre Pronchery err = 0;
263*e7be843bSPierre Pronchery r = safe_div_round_up_size_t(a, b, &err);
264*e7be843bSPierre Pronchery if (!TEST_int_eq(err, test_size_ts[n].div_round_up_err)
265*e7be843bSPierre Pronchery || (!err && !TEST_size_t_eq(r, a / b + (a % b != 0))))
266*e7be843bSPierre Pronchery goto err;
267*e7be843bSPierre Pronchery
268*e7be843bSPierre Pronchery err = 0;
269*e7be843bSPierre Pronchery r = safe_neg_size_t(a, &err);
270*e7be843bSPierre Pronchery if (!TEST_int_eq(err, a != 0) || (!err && !TEST_size_t_eq(r, 0)))
271*e7be843bSPierre Pronchery goto err;
272*e7be843bSPierre Pronchery
273*e7be843bSPierre Pronchery err = 0;
274*e7be843bSPierre Pronchery r = safe_neg_size_t(b, &err);
275*e7be843bSPierre Pronchery if (!TEST_int_eq(err, b != 0) || (!err && !TEST_size_t_eq(r, 0)))
276*e7be843bSPierre Pronchery goto err;
277*e7be843bSPierre Pronchery
278*e7be843bSPierre Pronchery err = 0;
279*e7be843bSPierre Pronchery r = safe_abs_size_t(a, &err);
280*e7be843bSPierre Pronchery if (!TEST_int_eq(err, 0) || !TEST_size_t_eq(r, a))
281*e7be843bSPierre Pronchery goto err;
282*e7be843bSPierre Pronchery
283*e7be843bSPierre Pronchery err = 0;
284*e7be843bSPierre Pronchery r = safe_abs_size_t(b, &err);
285*e7be843bSPierre Pronchery if (!TEST_int_eq(err, 0) || !TEST_size_t_eq(r, b))
286*e7be843bSPierre Pronchery goto err;
287*e7be843bSPierre Pronchery return 1;
288*e7be843bSPierre Pronchery err:
289*e7be843bSPierre Pronchery TEST_info("a = %zu b = %zu r = %zu err = %d", a, b, r, err);
290*e7be843bSPierre Pronchery return 0;
291*e7be843bSPierre Pronchery }
292*e7be843bSPierre Pronchery
293*e7be843bSPierre Pronchery static const struct {
294*e7be843bSPierre Pronchery int a, b, c;
295*e7be843bSPierre Pronchery int err;
296*e7be843bSPierre Pronchery } test_muldiv_ints[] = {
297*e7be843bSPierre Pronchery { 3, 1, 2, 0 },
298*e7be843bSPierre Pronchery { 1, 3, 2, 0 },
299*e7be843bSPierre Pronchery { -3, 1, 2, 0 },
300*e7be843bSPierre Pronchery { 1, 3, -2, 0 },
301*e7be843bSPierre Pronchery { INT_MAX, INT_MAX, INT_MAX, 0 },
302*e7be843bSPierre Pronchery { INT_MIN, INT_MIN, INT_MAX, 1 },
303*e7be843bSPierre Pronchery { INT_MIN, INT_MIN, INT_MIN, 0 },
304*e7be843bSPierre Pronchery { INT_MAX, 2, 4, 0 },
305*e7be843bSPierre Pronchery { 8, INT_MAX, 4, 1 },
306*e7be843bSPierre Pronchery { INT_MAX, 8, 4, 1 },
307*e7be843bSPierre Pronchery { INT_MIN, 2, 4, 1 },
308*e7be843bSPierre Pronchery { 8, INT_MIN, 4, 1 },
309*e7be843bSPierre Pronchery { INT_MIN, 8, 4, 1 },
310*e7be843bSPierre Pronchery { 3, 4, 0, 1 },
311*e7be843bSPierre Pronchery };
312*e7be843bSPierre Pronchery
test_int_muldiv(int n)313*e7be843bSPierre Pronchery static int test_int_muldiv(int n)
314*e7be843bSPierre Pronchery {
315*e7be843bSPierre Pronchery int err = 0;
316*e7be843bSPierre Pronchery int r, real = 0;
317*e7be843bSPierre Pronchery const int a = test_muldiv_ints[n].a;
318*e7be843bSPierre Pronchery const int b = test_muldiv_ints[n].b;
319*e7be843bSPierre Pronchery const int c = test_muldiv_ints[n].c;
320*e7be843bSPierre Pronchery
321*e7be843bSPierre Pronchery r = safe_muldiv_int(a, b, c, &err);
322*e7be843bSPierre Pronchery if (c != 0)
323*e7be843bSPierre Pronchery real = (int)((int64_t)a * (int64_t)b / (int64_t)c);
324*e7be843bSPierre Pronchery if (!TEST_int_eq(err, test_muldiv_ints[n].err)
325*e7be843bSPierre Pronchery || (!err && !TEST_int_eq(r, real))) {
326*e7be843bSPierre Pronchery TEST_info("%d * %d / %d r = %d err = %d", a, b, c, r, err);
327*e7be843bSPierre Pronchery return 0;
328*e7be843bSPierre Pronchery }
329*e7be843bSPierre Pronchery return 1;
330*e7be843bSPierre Pronchery }
331*e7be843bSPierre Pronchery
332*e7be843bSPierre Pronchery static const struct {
333*e7be843bSPierre Pronchery unsigned int a, b, c;
334*e7be843bSPierre Pronchery int err;
335*e7be843bSPierre Pronchery } test_muldiv_uints[] = {
336*e7be843bSPierre Pronchery { 3, 1, 2, 0 },
337*e7be843bSPierre Pronchery { 1, 3, 2, 0 },
338*e7be843bSPierre Pronchery { UINT_MAX, UINT_MAX, UINT_MAX, 0 },
339*e7be843bSPierre Pronchery { UINT_MAX, 2, 4, 0 },
340*e7be843bSPierre Pronchery { 8, UINT_MAX, 4, 1 },
341*e7be843bSPierre Pronchery { UINT_MAX, 8, 4, 1 },
342*e7be843bSPierre Pronchery { 3, 4, 0, 1 },
343*e7be843bSPierre Pronchery };
344*e7be843bSPierre Pronchery
test_uint_muldiv(int n)345*e7be843bSPierre Pronchery static int test_uint_muldiv(int n)
346*e7be843bSPierre Pronchery {
347*e7be843bSPierre Pronchery int err = 0;
348*e7be843bSPierre Pronchery unsigned int r, real = 0;
349*e7be843bSPierre Pronchery const unsigned int a = test_muldiv_uints[n].a;
350*e7be843bSPierre Pronchery const unsigned int b = test_muldiv_uints[n].b;
351*e7be843bSPierre Pronchery const unsigned int c = test_muldiv_uints[n].c;
352*e7be843bSPierre Pronchery
353*e7be843bSPierre Pronchery r = safe_muldiv_uint(a, b, c, &err);
354*e7be843bSPierre Pronchery if (c != 0)
355*e7be843bSPierre Pronchery real = (unsigned int)((uint64_t)a * (uint64_t)b / (uint64_t)c);
356*e7be843bSPierre Pronchery if (!TEST_int_eq(err, test_muldiv_uints[n].err)
357*e7be843bSPierre Pronchery || (!err && !TEST_uint_eq(r, real))) {
358*e7be843bSPierre Pronchery TEST_info("%u * %u / %u r = %u err = %d", a, b, c, r, err);
359*e7be843bSPierre Pronchery return 0;
360*e7be843bSPierre Pronchery }
361*e7be843bSPierre Pronchery return 1;
362*e7be843bSPierre Pronchery }
363*e7be843bSPierre Pronchery
setup_tests(void)364*e7be843bSPierre Pronchery int setup_tests(void)
365*e7be843bSPierre Pronchery {
366*e7be843bSPierre Pronchery ADD_ALL_TESTS(test_int_ops, OSSL_NELEM(test_ints));
367*e7be843bSPierre Pronchery ADD_ALL_TESTS(test_uint_ops, OSSL_NELEM(test_uints));
368*e7be843bSPierre Pronchery ADD_ALL_TESTS(test_size_t_ops, OSSL_NELEM(test_size_ts));
369*e7be843bSPierre Pronchery ADD_ALL_TESTS(test_int_muldiv, OSSL_NELEM(test_muldiv_ints));
370*e7be843bSPierre Pronchery ADD_ALL_TESTS(test_uint_muldiv, OSSL_NELEM(test_muldiv_uints));
371*e7be843bSPierre Pronchery return 1;
372*e7be843bSPierre Pronchery }
373