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