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