Blame gnulib/lib/xsize.h

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