Blame gnulib-tests/xsize.h

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