Blame lib/xsize.h

Packit 8f70b4
/* xsize.h -- Checked size_t computations.
Packit 8f70b4
Packit 8f70b4
   Copyright (C) 2003, 2008-2018 Free Software Foundation, Inc.
Packit 8f70b4
Packit 8f70b4
   This program is free software; you can redistribute it and/or modify
Packit 8f70b4
   it under the terms of the GNU General Public License as published by
Packit 8f70b4
   the Free Software Foundation; either version 3, or (at your option)
Packit 8f70b4
   any later version.
Packit 8f70b4
Packit 8f70b4
   This program is distributed in the hope that it will be useful,
Packit 8f70b4
   but WITHOUT ANY WARRANTY; without even the implied warranty of
Packit 8f70b4
   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
Packit 8f70b4
   GNU General Public License for more details.
Packit 8f70b4
Packit 8f70b4
   You should have received a copy of the GNU General Public License
Packit 8f70b4
   along with this program; if not, see <https://www.gnu.org/licenses/>.  */
Packit 8f70b4
Packit 8f70b4
#ifndef _XSIZE_H
Packit 8f70b4
#define _XSIZE_H
Packit 8f70b4
Packit 8f70b4
/* Get size_t.  */
Packit 8f70b4
#include <stddef.h>
Packit 8f70b4
Packit 8f70b4
/* Get SIZE_MAX.  */
Packit 8f70b4
#include <limits.h>
Packit 8f70b4
#if HAVE_STDINT_H
Packit 8f70b4
# include <stdint.h>
Packit 8f70b4
#endif
Packit 8f70b4
Packit 8f70b4
#ifndef _GL_INLINE_HEADER_BEGIN
Packit 8f70b4
 #error "Please include config.h first."
Packit 8f70b4
#endif
Packit 8f70b4
_GL_INLINE_HEADER_BEGIN
Packit 8f70b4
#ifndef XSIZE_INLINE
Packit 8f70b4
# define XSIZE_INLINE _GL_INLINE
Packit 8f70b4
#endif
Packit 8f70b4
Packit 8f70b4
/* The size of memory objects is often computed through expressions of
Packit 8f70b4
   type size_t. Example:
Packit 8f70b4
      void* p = malloc (header_size + n * element_size).
Packit 8f70b4
   These computations can lead to overflow.  When this happens, malloc()
Packit 8f70b4
   returns a piece of memory that is way too small, and the program then
Packit 8f70b4
   crashes while attempting to fill the memory.
Packit 8f70b4
   To avoid this, the functions and macros in this file check for overflow.
Packit 8f70b4
   The convention is that SIZE_MAX represents overflow.
Packit 8f70b4
   malloc (SIZE_MAX) is not guaranteed to fail -- think of a malloc
Packit 8f70b4
   implementation that uses mmap --, it's recommended to use size_overflow_p()
Packit 8f70b4
   or size_in_bounds_p() before invoking malloc().
Packit 8f70b4
   The example thus becomes:
Packit 8f70b4
      size_t size = xsum (header_size, xtimes (n, element_size));
Packit 8f70b4
      void *p = (size_in_bounds_p (size) ? malloc (size) : NULL);
Packit 8f70b4
*/
Packit 8f70b4
Packit 8f70b4
/* Convert an arbitrary value >= 0 to type size_t.  */
Packit 8f70b4
#define xcast_size_t(N) \
Packit 8f70b4
  ((N) <= SIZE_MAX ? (size_t) (N) : SIZE_MAX)
Packit 8f70b4
Packit 8f70b4
/* Sum of two sizes, with overflow check.  */
Packit 8f70b4
XSIZE_INLINE size_t
Packit 8f70b4
#if __GNUC__ >= 3
Packit 8f70b4
__attribute__ ((__pure__))
Packit 8f70b4
#endif
Packit 8f70b4
xsum (size_t size1, size_t size2)
Packit 8f70b4
{
Packit 8f70b4
  size_t sum = size1 + size2;
Packit 8f70b4
  return (sum >= size1 ? sum : SIZE_MAX);
Packit 8f70b4
}
Packit 8f70b4
Packit 8f70b4
/* Sum of three sizes, with overflow check.  */
Packit 8f70b4
XSIZE_INLINE size_t
Packit 8f70b4
#if __GNUC__ >= 3
Packit 8f70b4
__attribute__ ((__pure__))
Packit 8f70b4
#endif
Packit 8f70b4
xsum3 (size_t size1, size_t size2, size_t size3)
Packit 8f70b4
{
Packit 8f70b4
  return xsum (xsum (size1, size2), size3);
Packit 8f70b4
}
Packit 8f70b4
Packit 8f70b4
/* Sum of four sizes, with overflow check.  */
Packit 8f70b4
XSIZE_INLINE size_t
Packit 8f70b4
#if __GNUC__ >= 3
Packit 8f70b4
__attribute__ ((__pure__))
Packit 8f70b4
#endif
Packit 8f70b4
xsum4 (size_t size1, size_t size2, size_t size3, size_t size4)
Packit 8f70b4
{
Packit 8f70b4
  return xsum (xsum (xsum (size1, size2), size3), size4);
Packit 8f70b4
}
Packit 8f70b4
Packit 8f70b4
/* Maximum of two sizes, with overflow check.  */
Packit 8f70b4
XSIZE_INLINE size_t
Packit 8f70b4
#if __GNUC__ >= 3
Packit 8f70b4
__attribute__ ((__pure__))
Packit 8f70b4
#endif
Packit 8f70b4
xmax (size_t size1, size_t size2)
Packit 8f70b4
{
Packit 8f70b4
  /* No explicit check is needed here, because for any n:
Packit 8f70b4
     max (SIZE_MAX, n) == SIZE_MAX and max (n, SIZE_MAX) == SIZE_MAX.  */
Packit 8f70b4
  return (size1 >= size2 ? size1 : size2);
Packit 8f70b4
}
Packit 8f70b4
Packit 8f70b4
/* Multiplication of a count with an element size, with overflow check.
Packit 8f70b4
   The count must be >= 0 and the element size must be > 0.
Packit 8f70b4
   This is a macro, not a function, so that it works correctly even
Packit 8f70b4
   when N is of a wider type and N > SIZE_MAX.  */
Packit 8f70b4
#define xtimes(N, ELSIZE) \
Packit 8f70b4
  ((N) <= SIZE_MAX / (ELSIZE) ? (size_t) (N) * (ELSIZE) : SIZE_MAX)
Packit 8f70b4
Packit 8f70b4
/* Check for overflow.  */
Packit 8f70b4
#define size_overflow_p(SIZE) \
Packit 8f70b4
  ((SIZE) == SIZE_MAX)
Packit 8f70b4
/* Check against overflow.  */
Packit 8f70b4
#define size_in_bounds_p(SIZE) \
Packit 8f70b4
  ((SIZE) != SIZE_MAX)
Packit 8f70b4
Packit 8f70b4
_GL_INLINE_HEADER_END
Packit 8f70b4
Packit 8f70b4
#endif /* _XSIZE_H */