Blame lib/xsize.h

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