diff options
Diffstat (limited to 'gl/xalloc-oversized.h')
-rw-r--r-- | gl/xalloc-oversized.h | 79 |
1 files changed, 53 insertions, 26 deletions
diff --git a/gl/xalloc-oversized.h b/gl/xalloc-oversized.h index a971c78a..5dbdfb55 100644 --- a/gl/xalloc-oversized.h +++ b/gl/xalloc-oversized.h | |||
@@ -1,38 +1,65 @@ | |||
1 | /* xalloc-oversized.h -- memory allocation size checking | 1 | /* xalloc-oversized.h -- memory allocation size checking |
2 | 2 | ||
3 | Copyright (C) 1990-2000, 2003-2004, 2006-2013 Free Software Foundation, Inc. | 3 | Copyright (C) 1990-2000, 2003-2004, 2006-2023 Free Software Foundation, Inc. |
4 | 4 | ||
5 | This program is free software: you can redistribute it and/or modify | 5 | This file is free software: you can redistribute it and/or modify |
6 | it under the terms of the GNU General Public License as published by | 6 | it under the terms of the GNU Lesser General Public License as |
7 | the Free Software Foundation; either version 3 of the License, or | 7 | published by the Free Software Foundation; either version 2.1 of the |
8 | (at your option) any later version. | 8 | License, or (at your option) any later version. |
9 | 9 | ||
10 | This program is distributed in the hope that it will be useful, | 10 | This file is distributed in the hope that it will be useful, |
11 | but WITHOUT ANY WARRANTY; without even the implied warranty of | 11 | but WITHOUT ANY WARRANTY; without even the implied warranty of |
12 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | 12 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
13 | GNU General Public License for more details. | 13 | GNU Lesser General Public License for more details. |
14 | 14 | ||
15 | You should have received a copy of the GNU General Public License | 15 | You should have received a copy of the GNU Lesser General Public License |
16 | along with this program. If not, see <http://www.gnu.org/licenses/>. */ | 16 | along with this program. If not, see <https://www.gnu.org/licenses/>. */ |
17 | 17 | ||
18 | #ifndef XALLOC_OVERSIZED_H_ | 18 | #ifndef XALLOC_OVERSIZED_H_ |
19 | # define XALLOC_OVERSIZED_H_ | 19 | #define XALLOC_OVERSIZED_H_ |
20 | 20 | ||
21 | # include <stddef.h> | 21 | #include <stddef.h> |
22 | 22 | #include <stdint.h> | |
23 | /* Return 1 if an array of N objects, each of size S, cannot exist due | 23 | |
24 | to size arithmetic overflow. S must be positive and N must be | 24 | /* True if N * S does not fit into both ptrdiff_t and size_t. |
25 | nonnegative. This is a macro, not a function, so that it | 25 | N and S should be nonnegative and free of side effects. |
26 | works correctly even when SIZE_MAX < N. | 26 | This expands to a constant expression if N and S are both constants. |
27 | 27 | By gnulib convention, SIZE_MAX represents overflow in size_t | |
28 | By gnulib convention, SIZE_MAX represents overflow in size | 28 | calculations, so the conservative size_t-based dividend to use here |
29 | calculations, so the conservative dividend to use here is | 29 | is SIZE_MAX - 1. */ |
30 | SIZE_MAX - 1, since SIZE_MAX might represent an overflowed value. | 30 | #define __xalloc_oversized(n, s) \ |
31 | However, malloc (SIZE_MAX) fails on all known hosts where | 31 | ((s) != 0 \ |
32 | sizeof (ptrdiff_t) <= sizeof (size_t), so do not bother to test for | 32 | && ((size_t) (PTRDIFF_MAX < SIZE_MAX ? PTRDIFF_MAX : SIZE_MAX - 1) / (s) \ |
33 | exactly-SIZE_MAX allocations on such hosts; this avoids a test and | 33 | < (n))) |
34 | branch when S is known to be 1. */ | 34 | |
35 | /* Return 1 if and only if an array of N objects, each of size S, | ||
36 | cannot exist reliably because its total size in bytes would exceed | ||
37 | MIN (PTRDIFF_MAX, SIZE_MAX - 1). | ||
38 | |||
39 | N and S should be nonnegative and free of side effects. | ||
40 | |||
41 | Warning: (xalloc_oversized (N, S) ? NULL : malloc (N * S)) can | ||
42 | misbehave if N and S are both narrower than ptrdiff_t and size_t, | ||
43 | and can be rewritten as (xalloc_oversized (N, S) ? NULL | ||
44 | : malloc (N * (size_t) S)). | ||
45 | |||
46 | This is a macro, not a function, so that it works even if an | ||
47 | argument exceeds MAX (PTRDIFF_MAX, SIZE_MAX). */ | ||
48 | #if 7 <= __GNUC__ && !defined __clang__ && PTRDIFF_MAX < SIZE_MAX | ||
35 | # define xalloc_oversized(n, s) \ | 49 | # define xalloc_oversized(n, s) \ |
36 | ((size_t) (sizeof (ptrdiff_t) <= sizeof (size_t) ? -1 : -2) / (s) < (n)) | 50 | __builtin_mul_overflow_p (n, s, (ptrdiff_t) 1) |
51 | #elif (5 <= __GNUC__ && !defined __ICC && !__STRICT_ANSI__ \ | ||
52 | && PTRDIFF_MAX < SIZE_MAX) | ||
53 | # define xalloc_oversized(n, s) \ | ||
54 | (__builtin_constant_p (n) && __builtin_constant_p (s) \ | ||
55 | ? __xalloc_oversized (n, s) \ | ||
56 | : ({ ptrdiff_t __xalloc_count; \ | ||
57 | __builtin_mul_overflow (n, s, &__xalloc_count); })) | ||
58 | |||
59 | /* Other compilers use integer division; this may be slower but is | ||
60 | more portable. */ | ||
61 | #else | ||
62 | # define xalloc_oversized(n, s) __xalloc_oversized (n, s) | ||
63 | #endif | ||
37 | 64 | ||
38 | #endif /* !XALLOC_OVERSIZED_H_ */ | 65 | #endif /* !XALLOC_OVERSIZED_H_ */ |