Blame intl/xsize.h

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