xref: /dflybsd-src/contrib/cvs-1.12/lib/xsize.h (revision 86d7f5d305c6adaa56ff4582ece9859d73106103)
186d7f5d3SJohn Marino /* xsize.h -- Checked size_t computations.
286d7f5d3SJohn Marino 
386d7f5d3SJohn Marino    Copyright (C) 2003 Free Software Foundation, Inc.
486d7f5d3SJohn Marino 
586d7f5d3SJohn Marino    This program is free software; you can redistribute it and/or modify
686d7f5d3SJohn Marino    it under the terms of the GNU General Public License as published by
786d7f5d3SJohn Marino    the Free Software Foundation; either version 2, or (at your option)
886d7f5d3SJohn Marino    any later version.
986d7f5d3SJohn Marino 
1086d7f5d3SJohn Marino    This program is distributed in the hope that it will be useful,
1186d7f5d3SJohn Marino    but WITHOUT ANY WARRANTY; without even the implied warranty of
1286d7f5d3SJohn Marino    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
1386d7f5d3SJohn Marino    GNU General Public License for more details.
1486d7f5d3SJohn Marino 
1586d7f5d3SJohn Marino    You should have received a copy of the GNU General Public License
1686d7f5d3SJohn Marino    along with this program; if not, write to the Free Software Foundation,
1786d7f5d3SJohn Marino    Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.  */
1886d7f5d3SJohn Marino 
1986d7f5d3SJohn Marino #ifndef _XSIZE_H
2086d7f5d3SJohn Marino #define _XSIZE_H
2186d7f5d3SJohn Marino 
2286d7f5d3SJohn Marino /* Get size_t.  */
2386d7f5d3SJohn Marino #include <stddef.h>
2486d7f5d3SJohn Marino 
2586d7f5d3SJohn Marino /* Get SIZE_MAX.  */
2686d7f5d3SJohn Marino #include <limits.h>
2786d7f5d3SJohn Marino #if HAVE_STDINT_H
2886d7f5d3SJohn Marino # include <stdint.h>
2986d7f5d3SJohn Marino #endif
3086d7f5d3SJohn Marino 
3186d7f5d3SJohn Marino /* The size of memory objects is often computed through expressions of
3286d7f5d3SJohn Marino    type size_t. Example:
3386d7f5d3SJohn Marino       void* p = malloc (header_size + n * element_size).
3486d7f5d3SJohn Marino    These computations can lead to overflow.  When this happens, malloc()
3586d7f5d3SJohn Marino    returns a piece of memory that is way too small, and the program then
3686d7f5d3SJohn Marino    crashes while attempting to fill the memory.
3786d7f5d3SJohn Marino    To avoid this, the functions and macros in this file check for overflow.
3886d7f5d3SJohn Marino    The convention is that SIZE_MAX represents overflow.
3986d7f5d3SJohn Marino    malloc (SIZE_MAX) is not guaranteed to fail -- think of a malloc
4086d7f5d3SJohn Marino    implementation that uses mmap --, it's recommended to use size_overflow_p()
4186d7f5d3SJohn Marino    or size_in_bounds_p() before invoking malloc().
4286d7f5d3SJohn Marino    The example thus becomes:
4386d7f5d3SJohn Marino       size_t size = xsum (header_size, xtimes (n, element_size));
4486d7f5d3SJohn Marino       void *p = (size_in_bounds_p (size) ? malloc (size) : NULL);
4586d7f5d3SJohn Marino */
4686d7f5d3SJohn Marino 
4786d7f5d3SJohn Marino /* Convert an arbitrary value >= 0 to type size_t.  */
4886d7f5d3SJohn Marino #define xcast_size_t(N) \
4986d7f5d3SJohn Marino   ((N) <= SIZE_MAX ? (size_t) (N) : SIZE_MAX)
5086d7f5d3SJohn Marino 
5186d7f5d3SJohn Marino /* Sum of two sizes, with overflow check.  */
5286d7f5d3SJohn Marino static inline size_t
5386d7f5d3SJohn Marino #if __GNUC__ >= 3
5486d7f5d3SJohn Marino __attribute__ ((__pure__))
5586d7f5d3SJohn Marino #endif
xsum(size_t size1,size_t size2)5686d7f5d3SJohn Marino xsum (size_t size1, size_t size2)
5786d7f5d3SJohn Marino {
5886d7f5d3SJohn Marino   size_t sum = size1 + size2;
5986d7f5d3SJohn Marino   return (sum >= size1 ? sum : SIZE_MAX);
6086d7f5d3SJohn Marino }
6186d7f5d3SJohn Marino 
6286d7f5d3SJohn Marino /* Sum of three sizes, with overflow check.  */
6386d7f5d3SJohn Marino static inline size_t
6486d7f5d3SJohn Marino #if __GNUC__ >= 3
6586d7f5d3SJohn Marino __attribute__ ((__pure__))
6686d7f5d3SJohn Marino #endif
xsum3(size_t size1,size_t size2,size_t size3)6786d7f5d3SJohn Marino xsum3 (size_t size1, size_t size2, size_t size3)
6886d7f5d3SJohn Marino {
6986d7f5d3SJohn Marino   return xsum (xsum (size1, size2), size3);
7086d7f5d3SJohn Marino }
7186d7f5d3SJohn Marino 
7286d7f5d3SJohn Marino /* Sum of four sizes, with overflow check.  */
7386d7f5d3SJohn Marino static inline size_t
7486d7f5d3SJohn Marino #if __GNUC__ >= 3
7586d7f5d3SJohn Marino __attribute__ ((__pure__))
7686d7f5d3SJohn Marino #endif
xsum4(size_t size1,size_t size2,size_t size3,size_t size4)7786d7f5d3SJohn Marino xsum4 (size_t size1, size_t size2, size_t size3, size_t size4)
7886d7f5d3SJohn Marino {
7986d7f5d3SJohn Marino   return xsum (xsum (xsum (size1, size2), size3), size4);
8086d7f5d3SJohn Marino }
8186d7f5d3SJohn Marino 
8286d7f5d3SJohn Marino /* Maximum of two sizes, with overflow check.  */
8386d7f5d3SJohn Marino static inline size_t
8486d7f5d3SJohn Marino #if __GNUC__ >= 3
8586d7f5d3SJohn Marino __attribute__ ((__pure__))
8686d7f5d3SJohn Marino #endif
xmax(size_t size1,size_t size2)8786d7f5d3SJohn Marino xmax (size_t size1, size_t size2)
8886d7f5d3SJohn Marino {
8986d7f5d3SJohn Marino   /* No explicit check is needed here, because for any n:
9086d7f5d3SJohn Marino      max (SIZE_MAX, n) == SIZE_MAX and max (n, SIZE_MAX) == SIZE_MAX.  */
9186d7f5d3SJohn Marino   return (size1 >= size2 ? size1 : size2);
9286d7f5d3SJohn Marino }
9386d7f5d3SJohn Marino 
9486d7f5d3SJohn Marino /* Multiplication of a count with an element size, with overflow check.
9586d7f5d3SJohn Marino    The count must be >= 0 and the element size must be > 0.
9686d7f5d3SJohn Marino    This is a macro, not an inline function, so that it works correctly even
9786d7f5d3SJohn Marino    when N is of a wider tupe and N > SIZE_MAX.  */
9886d7f5d3SJohn Marino #define xtimes(N, ELSIZE) \
9986d7f5d3SJohn Marino   ((N) <= SIZE_MAX / (ELSIZE) ? (size_t) (N) * (ELSIZE) : SIZE_MAX)
10086d7f5d3SJohn Marino 
10186d7f5d3SJohn Marino /* Check for overflow.  */
10286d7f5d3SJohn Marino #define size_overflow_p(SIZE) \
10386d7f5d3SJohn Marino   ((SIZE) == SIZE_MAX)
10486d7f5d3SJohn Marino /* Check against overflow.  */
10586d7f5d3SJohn Marino #define size_in_bounds_p(SIZE) \
10686d7f5d3SJohn Marino   ((SIZE) != SIZE_MAX)
10786d7f5d3SJohn Marino 
10886d7f5d3SJohn Marino #endif /* _XSIZE_H */
109