xref: /openssl/test/safe_math_test.c (revision fecb3aae)
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 
test_int_ops(int n)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 
test_uint_ops(int n)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 
test_size_t_ops(int n)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 
test_int_muldiv(int n)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 
test_uint_muldiv(int n)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 
setup_tests(void)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 }
373