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