Blame gl/xsize.h

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