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