xref: /dflybsd-src/contrib/grep/lib/xalloc-oversized.h (revision 91b9ed38d3db6a8a8ac5b66da1d43e6e331e259a)
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