VirtualBox

source: vbox/trunk/src/libs/openssl-3.3.2/include/internal/safe_math.h@ 108403

最後變更 在這個檔案從108403是 108206,由 vboxsync 提交於 5 週 前

openssl-3.3.2: Exported all files to OSE and removed .scm-settings ​bugref:10757

  • 屬性 svn:eol-style 設為 native
  • 屬性 svn:keywords 設為 Author Date Id Revision
檔案大小: 25.4 KB
 
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#ifndef OSSL_INTERNAL_SAFE_MATH_H
11# define OSSL_INTERNAL_SAFE_MATH_H
12# pragma once
13
14# include <openssl/e_os2.h> /* For 'ossl_inline' */
15
16# ifndef OPENSSL_NO_BUILTIN_OVERFLOW_CHECKING
17# ifdef __has_builtin
18# define has(func) __has_builtin(func)
19# elif __GNUC__ > 5
20# define has(func) 1
21# endif
22# endif /* OPENSSL_NO_BUILTIN_OVERFLOW_CHECKING */
23
24# ifndef has
25# define has(func) 0
26# endif
27
28/*
29 * Safe addition helpers
30 */
31# if has(__builtin_add_overflow)
32# define OSSL_SAFE_MATH_ADDS(type_name, type, min, max) \
33 static ossl_inline ossl_unused type safe_add_ ## type_name(type a, \
34 type b, \
35 int *err) \
36 { \
37 type r; \
38 \
39 if (!__builtin_add_overflow(a, b, &r)) \
40 return r; \
41 *err |= 1; \
42 return a < 0 ? min : max; \
43 }
44
45# define OSSL_SAFE_MATH_ADDU(type_name, type, max) \
46 static ossl_inline ossl_unused type safe_add_ ## type_name(type a, \
47 type b, \
48 int *err) \
49 { \
50 type r; \
51 \
52 if (!__builtin_add_overflow(a, b, &r)) \
53 return r; \
54 *err |= 1; \
55 return a + b; \
56 }
57
58# else /* has(__builtin_add_overflow) */
59# define OSSL_SAFE_MATH_ADDS(type_name, type, min, max) \
60 static ossl_inline ossl_unused type safe_add_ ## type_name(type a, \
61 type b, \
62 int *err) \
63 { \
64 if ((a < 0) ^ (b < 0) \
65 || (a > 0 && b <= max - a) \
66 || (a < 0 && b >= min - a) \
67 || a == 0) \
68 return a + b; \
69 *err |= 1; \
70 return a < 0 ? min : max; \
71 }
72
73# define OSSL_SAFE_MATH_ADDU(type_name, type, max) \
74 static ossl_inline ossl_unused type safe_add_ ## type_name(type a, \
75 type b, \
76 int *err) \
77 { \
78 if (b > max - a) \
79 *err |= 1; \
80 return a + b; \
81 }
82# endif /* has(__builtin_add_overflow) */
83
84/*
85 * Safe subtraction helpers
86 */
87# if has(__builtin_sub_overflow)
88# define OSSL_SAFE_MATH_SUBS(type_name, type, min, max) \
89 static ossl_inline ossl_unused type safe_sub_ ## type_name(type a, \
90 type b, \
91 int *err) \
92 { \
93 type r; \
94 \
95 if (!__builtin_sub_overflow(a, b, &r)) \
96 return r; \
97 *err |= 1; \
98 return a < 0 ? min : max; \
99 }
100
101# else /* has(__builtin_sub_overflow) */
102# define OSSL_SAFE_MATH_SUBS(type_name, type, min, max) \
103 static ossl_inline ossl_unused type safe_sub_ ## type_name(type a, \
104 type b, \
105 int *err) \
106 { \
107 if (!((a < 0) ^ (b < 0)) \
108 || (b > 0 && a >= min + b) \
109 || (b < 0 && a <= max + b) \
110 || b == 0) \
111 return a - b; \
112 *err |= 1; \
113 return a < 0 ? min : max; \
114 }
115
116# endif /* has(__builtin_sub_overflow) */
117
118# define OSSL_SAFE_MATH_SUBU(type_name, type) \
119 static ossl_inline ossl_unused type safe_sub_ ## type_name(type a, \
120 type b, \
121 int *err) \
122 { \
123 if (b > a) \
124 *err |= 1; \
125 return a - b; \
126 }
127
128/*
129 * Safe multiplication helpers
130 */
131# if has(__builtin_mul_overflow)
132# define OSSL_SAFE_MATH_MULS(type_name, type, min, max) \
133 static ossl_inline ossl_unused type safe_mul_ ## type_name(type a, \
134 type b, \
135 int *err) \
136 { \
137 type r; \
138 \
139 if (!__builtin_mul_overflow(a, b, &r)) \
140 return r; \
141 *err |= 1; \
142 return (a < 0) ^ (b < 0) ? min : max; \
143 }
144
145# define OSSL_SAFE_MATH_MULU(type_name, type, max) \
146 static ossl_inline ossl_unused type safe_mul_ ## type_name(type a, \
147 type b, \
148 int *err) \
149 { \
150 type r; \
151 \
152 if (!__builtin_mul_overflow(a, b, &r)) \
153 return r; \
154 *err |= 1; \
155 return a * b; \
156 }
157
158# else /* has(__builtin_mul_overflow) */
159# define OSSL_SAFE_MATH_MULS(type_name, type, min, max) \
160 static ossl_inline ossl_unused type safe_mul_ ## type_name(type a, \
161 type b, \
162 int *err) \
163 { \
164 if (a == 0 || b == 0) \
165 return 0; \
166 if (a == 1) \
167 return b; \
168 if (b == 1) \
169 return a; \
170 if (a != min && b != min) { \
171 const type x = a < 0 ? -a : a; \
172 const type y = b < 0 ? -b : b; \
173 \
174 if (x <= max / y) \
175 return a * b; \
176 } \
177 *err |= 1; \
178 return (a < 0) ^ (b < 0) ? min : max; \
179 }
180
181# define OSSL_SAFE_MATH_MULU(type_name, type, max) \
182 static ossl_inline ossl_unused type safe_mul_ ## type_name(type a, \
183 type b, \
184 int *err) \
185 { \
186 if (b != 0 && a > max / b) \
187 *err |= 1; \
188 return a * b; \
189 }
190# endif /* has(__builtin_mul_overflow) */
191
192/*
193 * Safe division helpers
194 */
195# define OSSL_SAFE_MATH_DIVS(type_name, type, min, max) \
196 static ossl_inline ossl_unused type safe_div_ ## type_name(type a, \
197 type b, \
198 int *err) \
199 { \
200 if (b == 0) { \
201 *err |= 1; \
202 return a < 0 ? min : max; \
203 } \
204 if (b == -1 && a == min) { \
205 *err |= 1; \
206 return max; \
207 } \
208 return a / b; \
209 }
210
211# define OSSL_SAFE_MATH_DIVU(type_name, type, max) \
212 static ossl_inline ossl_unused type safe_div_ ## type_name(type a, \
213 type b, \
214 int *err) \
215 { \
216 if (b != 0) \
217 return a / b; \
218 *err |= 1; \
219 return max; \
220 }
221
222/*
223 * Safe modulus helpers
224 */
225# define OSSL_SAFE_MATH_MODS(type_name, type, min, max) \
226 static ossl_inline ossl_unused type safe_mod_ ## type_name(type a, \
227 type b, \
228 int *err) \
229 { \
230 if (b == 0) { \
231 *err |= 1; \
232 return 0; \
233 } \
234 if (b == -1 && a == min) { \
235 *err |= 1; \
236 return max; \
237 } \
238 return a % b; \
239 }
240
241# define OSSL_SAFE_MATH_MODU(type_name, type) \
242 static ossl_inline ossl_unused type safe_mod_ ## type_name(type a, \
243 type b, \
244 int *err) \
245 { \
246 if (b != 0) \
247 return a % b; \
248 *err |= 1; \
249 return 0; \
250 }
251
252/*
253 * Safe negation helpers
254 */
255# define OSSL_SAFE_MATH_NEGS(type_name, type, min) \
256 static ossl_inline ossl_unused type safe_neg_ ## type_name(type a, \
257 int *err) \
258 { \
259 if (a != min) \
260 return -a; \
261 *err |= 1; \
262 return min; \
263 }
264
265# define OSSL_SAFE_MATH_NEGU(type_name, type) \
266 static ossl_inline ossl_unused type safe_neg_ ## type_name(type a, \
267 int *err) \
268 { \
269 if (a == 0) \
270 return a; \
271 *err |= 1; \
272 return 1 + ~a; \
273 }
274
275/*
276 * Safe absolute value helpers
277 */
278# define OSSL_SAFE_MATH_ABSS(type_name, type, min) \
279 static ossl_inline ossl_unused type safe_abs_ ## type_name(type a, \
280 int *err) \
281 { \
282 if (a != min) \
283 return a < 0 ? -a : a; \
284 *err |= 1; \
285 return min; \
286 }
287
288# define OSSL_SAFE_MATH_ABSU(type_name, type) \
289 static ossl_inline ossl_unused type safe_abs_ ## type_name(type a, \
290 int *err) \
291 { \
292 return a; \
293 }
294
295/*
296 * Safe fused multiply divide helpers
297 *
298 * These are a bit obscure:
299 * . They begin by checking the denominator for zero and getting rid of this
300 * corner case.
301 *
302 * . Second is an attempt to do the multiplication directly, if it doesn't
303 * overflow, the quotient is returned (for signed values there is a
304 * potential problem here which isn't present for unsigned).
305 *
306 * . Finally, the multiplication/division is transformed so that the larger
307 * of the numerators is divided first. This requires a remainder
308 * correction:
309 *
310 * a b / c = (a / c) b + (a mod c) b / c, where a > b
311 *
312 * The individual operations need to be overflow checked (again signed
313 * being more problematic).
314 *
315 * The algorithm used is not perfect but it should be "good enough".
316 */
317# define OSSL_SAFE_MATH_MULDIVS(type_name, type, max) \
318 static ossl_inline ossl_unused type safe_muldiv_ ## type_name(type a, \
319 type b, \
320 type c, \
321 int *err) \
322 { \
323 int e2 = 0; \
324 type q, r, x, y; \
325 \
326 if (c == 0) { \
327 *err |= 1; \
328 return a == 0 || b == 0 ? 0 : max; \
329 } \
330 x = safe_mul_ ## type_name(a, b, &e2); \
331 if (!e2) \
332 return safe_div_ ## type_name(x, c, err); \
333 if (b > a) { \
334 x = b; \
335 b = a; \
336 a = x; \
337 } \
338 q = safe_div_ ## type_name(a, c, err); \
339 r = safe_mod_ ## type_name(a, c, err); \
340 x = safe_mul_ ## type_name(r, b, err); \
341 y = safe_mul_ ## type_name(q, b, err); \
342 q = safe_div_ ## type_name(x, c, err); \
343 return safe_add_ ## type_name(y, q, err); \
344 }
345
346# define OSSL_SAFE_MATH_MULDIVU(type_name, type, max) \
347 static ossl_inline ossl_unused type safe_muldiv_ ## type_name(type a, \
348 type b, \
349 type c, \
350 int *err) \
351 { \
352 int e2 = 0; \
353 type x, y; \
354 \
355 if (c == 0) { \
356 *err |= 1; \
357 return a == 0 || b == 0 ? 0 : max; \
358 } \
359 x = safe_mul_ ## type_name(a, b, &e2); \
360 if (!e2) \
361 return x / c; \
362 if (b > a) { \
363 x = b; \
364 b = a; \
365 a = x; \
366 } \
367 x = safe_mul_ ## type_name(a % c, b, err); \
368 y = safe_mul_ ## type_name(a / c, b, err); \
369 return safe_add_ ## type_name(y, x / c, err); \
370 }
371
372/*
373 * Calculate a / b rounding up:
374 * i.e. a / b + (a % b != 0)
375 * Which is usually (less safely) converted to (a + b - 1) / b
376 * If you *know* that b != 0, then it's safe to ignore err.
377 */
378#define OSSL_SAFE_MATH_DIV_ROUND_UP(type_name, type, max) \
379 static ossl_inline ossl_unused type safe_div_round_up_ ## type_name \
380 (type a, type b, int *errp) \
381 { \
382 type x; \
383 int *err, err_local = 0; \
384 \
385 /* Allow errors to be ignored by callers */ \
386 err = errp != NULL ? errp : &err_local; \
387 /* Fast path, both positive */ \
388 if (b > 0 && a > 0) { \
389 /* Faster path: no overflow concerns */ \
390 if (a < max - b) \
391 return (a + b - 1) / b; \
392 return a / b + (a % b != 0); \
393 } \
394 if (b == 0) { \
395 *err |= 1; \
396 return a == 0 ? 0 : max; \
397 } \
398 if (a == 0) \
399 return 0; \
400 /* Rather slow path because there are negatives involved */ \
401 x = safe_mod_ ## type_name(a, b, err); \
402 return safe_add_ ## type_name(safe_div_ ## type_name(a, b, err), \
403 x != 0, err); \
404 }
405
406/* Calculate ranges of types */
407# define OSSL_SAFE_MATH_MINS(type) ((type)1 << (sizeof(type) * 8 - 1))
408# define OSSL_SAFE_MATH_MAXS(type) (~OSSL_SAFE_MATH_MINS(type))
409# define OSSL_SAFE_MATH_MAXU(type) (~(type)0)
410
411/*
412 * Wrapper macros to create all the functions of a given type
413 */
414# define OSSL_SAFE_MATH_SIGNED(type_name, type) \
415 OSSL_SAFE_MATH_ADDS(type_name, type, OSSL_SAFE_MATH_MINS(type), \
416 OSSL_SAFE_MATH_MAXS(type)) \
417 OSSL_SAFE_MATH_SUBS(type_name, type, OSSL_SAFE_MATH_MINS(type), \
418 OSSL_SAFE_MATH_MAXS(type)) \
419 OSSL_SAFE_MATH_MULS(type_name, type, OSSL_SAFE_MATH_MINS(type), \
420 OSSL_SAFE_MATH_MAXS(type)) \
421 OSSL_SAFE_MATH_DIVS(type_name, type, OSSL_SAFE_MATH_MINS(type), \
422 OSSL_SAFE_MATH_MAXS(type)) \
423 OSSL_SAFE_MATH_MODS(type_name, type, OSSL_SAFE_MATH_MINS(type), \
424 OSSL_SAFE_MATH_MAXS(type)) \
425 OSSL_SAFE_MATH_DIV_ROUND_UP(type_name, type, \
426 OSSL_SAFE_MATH_MAXS(type)) \
427 OSSL_SAFE_MATH_MULDIVS(type_name, type, OSSL_SAFE_MATH_MAXS(type)) \
428 OSSL_SAFE_MATH_NEGS(type_name, type, OSSL_SAFE_MATH_MINS(type)) \
429 OSSL_SAFE_MATH_ABSS(type_name, type, OSSL_SAFE_MATH_MINS(type))
430
431# define OSSL_SAFE_MATH_UNSIGNED(type_name, type) \
432 OSSL_SAFE_MATH_ADDU(type_name, type, OSSL_SAFE_MATH_MAXU(type)) \
433 OSSL_SAFE_MATH_SUBU(type_name, type) \
434 OSSL_SAFE_MATH_MULU(type_name, type, OSSL_SAFE_MATH_MAXU(type)) \
435 OSSL_SAFE_MATH_DIVU(type_name, type, OSSL_SAFE_MATH_MAXU(type)) \
436 OSSL_SAFE_MATH_MODU(type_name, type) \
437 OSSL_SAFE_MATH_DIV_ROUND_UP(type_name, type, \
438 OSSL_SAFE_MATH_MAXU(type)) \
439 OSSL_SAFE_MATH_MULDIVU(type_name, type, OSSL_SAFE_MATH_MAXU(type)) \
440 OSSL_SAFE_MATH_NEGU(type_name, type) \
441 OSSL_SAFE_MATH_ABSU(type_name, type)
442
443#endif /* OSSL_INTERNAL_SAFE_MATH_H */
注意: 瀏覽 TracBrowser 來幫助您使用儲存庫瀏覽器

© 2025 Oracle Support Privacy / Do Not Sell My Info Terms of Use Trademark Policy Automated Access Etiquette