1200fbe8dSJohn Marino /* xalloc-oversized.h -- memory allocation size checking 2200fbe8dSJohn Marino 3*09d4459fSDaniel Fojt Copyright (C) 1990-2000, 2003-2004, 2006-2020 Free Software Foundation, Inc. 4200fbe8dSJohn Marino 5200fbe8dSJohn Marino This program is free software: you can redistribute it and/or modify 6200fbe8dSJohn Marino it under the terms of the GNU General Public License as published by 7200fbe8dSJohn Marino the Free Software Foundation; either version 3 of the License, or 8200fbe8dSJohn Marino (at your option) any later version. 9200fbe8dSJohn Marino 10200fbe8dSJohn Marino This program is distributed in the hope that it will be useful, 11200fbe8dSJohn Marino but WITHOUT ANY WARRANTY; without even the implied warranty of 12200fbe8dSJohn Marino MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13200fbe8dSJohn Marino GNU General Public License for more details. 14200fbe8dSJohn Marino 15200fbe8dSJohn Marino You should have received a copy of the GNU General Public License 16*09d4459fSDaniel Fojt along with this program. If not, see <https://www.gnu.org/licenses/>. */ 17200fbe8dSJohn Marino 18200fbe8dSJohn Marino #ifndef XALLOC_OVERSIZED_H_ 19200fbe8dSJohn Marino #define XALLOC_OVERSIZED_H_ 20200fbe8dSJohn Marino 21200fbe8dSJohn Marino #include <stddef.h> 22*09d4459fSDaniel Fojt #include <stdint.h> 23200fbe8dSJohn Marino 24*09d4459fSDaniel Fojt /* True if N * S would overflow in a size_t calculation, 25*09d4459fSDaniel Fojt or would generate a value larger than PTRDIFF_MAX. 26*09d4459fSDaniel Fojt This expands to a constant expression if N and S are both constants. 27200fbe8dSJohn Marino By gnulib convention, SIZE_MAX represents overflow in size 28*09d4459fSDaniel Fojt calculations, so the conservative size_t-based dividend to use here 29*09d4459fSDaniel Fojt is SIZE_MAX - 1. */ 30*09d4459fSDaniel Fojt #define __xalloc_oversized(n, s) \ 31*09d4459fSDaniel Fojt ((size_t) (PTRDIFF_MAX < SIZE_MAX ? PTRDIFF_MAX : SIZE_MAX - 1) / (s) < (n)) 32*09d4459fSDaniel Fojt 33*09d4459fSDaniel Fojt #if PTRDIFF_MAX < SIZE_MAX 34*09d4459fSDaniel Fojt typedef ptrdiff_t __xalloc_count_type; 35*09d4459fSDaniel Fojt #else 36*09d4459fSDaniel Fojt typedef size_t __xalloc_count_type; 37*09d4459fSDaniel Fojt #endif 38*09d4459fSDaniel Fojt 39*09d4459fSDaniel Fojt /* Return 1 if an array of N objects, each of size S, cannot exist 40*09d4459fSDaniel Fojt reliably due to size or ptrdiff_t arithmetic overflow. S must be 41*09d4459fSDaniel Fojt positive and N must be nonnegative. This is a macro, not a 42*09d4459fSDaniel Fojt function, so that it works correctly even when SIZE_MAX < N. */ 43*09d4459fSDaniel Fojt 44*09d4459fSDaniel Fojt #if 7 <= __GNUC__ 45200fbe8dSJohn Marino # define xalloc_oversized(n, s) \ 46*09d4459fSDaniel Fojt __builtin_mul_overflow_p (n, s, (__xalloc_count_type) 1) 47*09d4459fSDaniel Fojt #elif 5 <= __GNUC__ && !defined __ICC && !__STRICT_ANSI__ 48*09d4459fSDaniel Fojt # define xalloc_oversized(n, s) \ 49*09d4459fSDaniel Fojt (__builtin_constant_p (n) && __builtin_constant_p (s) \ 50*09d4459fSDaniel Fojt ? __xalloc_oversized (n, s) \ 51*09d4459fSDaniel Fojt : ({ __xalloc_count_type __xalloc_count; \ 52*09d4459fSDaniel Fojt __builtin_mul_overflow (n, s, &__xalloc_count); })) 53*09d4459fSDaniel Fojt 54*09d4459fSDaniel Fojt /* Other compilers use integer division; this may be slower but is 55*09d4459fSDaniel Fojt more portable. */ 56*09d4459fSDaniel Fojt #else 57*09d4459fSDaniel Fojt # define xalloc_oversized(n, s) __xalloc_oversized (n, s) 58*09d4459fSDaniel Fojt #endif 59200fbe8dSJohn Marino 60200fbe8dSJohn Marino #endif /* !XALLOC_OVERSIZED_H_ */ 61