Blame gnulib/lib/xsize.h

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