105436638acc7c010349a69c3395f1a57c642dc62Ying Wang/* xsize.h -- Checked size_t computations.
205436638acc7c010349a69c3395f1a57c642dc62Ying Wang
305436638acc7c010349a69c3395f1a57c642dc62Ying Wang   Copyright (C) 2003, 2008-2012 Free Software Foundation, Inc.
405436638acc7c010349a69c3395f1a57c642dc62Ying Wang
505436638acc7c010349a69c3395f1a57c642dc62Ying Wang   This program is free software; you can redistribute it and/or modify
605436638acc7c010349a69c3395f1a57c642dc62Ying Wang   it under the terms of the GNU General Public License as published by
705436638acc7c010349a69c3395f1a57c642dc62Ying Wang   the Free Software Foundation; either version 3, or (at your option)
805436638acc7c010349a69c3395f1a57c642dc62Ying Wang   any later version.
905436638acc7c010349a69c3395f1a57c642dc62Ying Wang
1005436638acc7c010349a69c3395f1a57c642dc62Ying Wang   This program is distributed in the hope that it will be useful,
1105436638acc7c010349a69c3395f1a57c642dc62Ying Wang   but WITHOUT ANY WARRANTY; without even the implied warranty of
1205436638acc7c010349a69c3395f1a57c642dc62Ying Wang   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
1305436638acc7c010349a69c3395f1a57c642dc62Ying Wang   GNU General Public License for more details.
1405436638acc7c010349a69c3395f1a57c642dc62Ying Wang
1505436638acc7c010349a69c3395f1a57c642dc62Ying Wang   You should have received a copy of the GNU General Public License
1605436638acc7c010349a69c3395f1a57c642dc62Ying Wang   along with this program; if not, see <http://www.gnu.org/licenses/>.  */
1705436638acc7c010349a69c3395f1a57c642dc62Ying Wang
1805436638acc7c010349a69c3395f1a57c642dc62Ying Wang#ifndef _XSIZE_H
1905436638acc7c010349a69c3395f1a57c642dc62Ying Wang#define _XSIZE_H
2005436638acc7c010349a69c3395f1a57c642dc62Ying Wang
2105436638acc7c010349a69c3395f1a57c642dc62Ying Wang/* Get size_t.  */
2205436638acc7c010349a69c3395f1a57c642dc62Ying Wang#include <stddef.h>
2305436638acc7c010349a69c3395f1a57c642dc62Ying Wang
2405436638acc7c010349a69c3395f1a57c642dc62Ying Wang/* Get SIZE_MAX.  */
2505436638acc7c010349a69c3395f1a57c642dc62Ying Wang#include <limits.h>
2605436638acc7c010349a69c3395f1a57c642dc62Ying Wang#if HAVE_STDINT_H
2705436638acc7c010349a69c3395f1a57c642dc62Ying Wang# include <stdint.h>
2805436638acc7c010349a69c3395f1a57c642dc62Ying Wang#endif
2905436638acc7c010349a69c3395f1a57c642dc62Ying Wang
3005436638acc7c010349a69c3395f1a57c642dc62Ying Wang_GL_INLINE_HEADER_BEGIN
3105436638acc7c010349a69c3395f1a57c642dc62Ying Wang#ifndef XSIZE_INLINE
3205436638acc7c010349a69c3395f1a57c642dc62Ying Wang# define XSIZE_INLINE _GL_INLINE
3305436638acc7c010349a69c3395f1a57c642dc62Ying Wang#endif
3405436638acc7c010349a69c3395f1a57c642dc62Ying Wang
3505436638acc7c010349a69c3395f1a57c642dc62Ying Wang/* The size of memory objects is often computed through expressions of
3605436638acc7c010349a69c3395f1a57c642dc62Ying Wang   type size_t. Example:
3705436638acc7c010349a69c3395f1a57c642dc62Ying Wang      void* p = malloc (header_size + n * element_size).
3805436638acc7c010349a69c3395f1a57c642dc62Ying Wang   These computations can lead to overflow.  When this happens, malloc()
3905436638acc7c010349a69c3395f1a57c642dc62Ying Wang   returns a piece of memory that is way too small, and the program then
4005436638acc7c010349a69c3395f1a57c642dc62Ying Wang   crashes while attempting to fill the memory.
4105436638acc7c010349a69c3395f1a57c642dc62Ying Wang   To avoid this, the functions and macros in this file check for overflow.
4205436638acc7c010349a69c3395f1a57c642dc62Ying Wang   The convention is that SIZE_MAX represents overflow.
4305436638acc7c010349a69c3395f1a57c642dc62Ying Wang   malloc (SIZE_MAX) is not guaranteed to fail -- think of a malloc
4405436638acc7c010349a69c3395f1a57c642dc62Ying Wang   implementation that uses mmap --, it's recommended to use size_overflow_p()
4505436638acc7c010349a69c3395f1a57c642dc62Ying Wang   or size_in_bounds_p() before invoking malloc().
4605436638acc7c010349a69c3395f1a57c642dc62Ying Wang   The example thus becomes:
4705436638acc7c010349a69c3395f1a57c642dc62Ying Wang      size_t size = xsum (header_size, xtimes (n, element_size));
4805436638acc7c010349a69c3395f1a57c642dc62Ying Wang      void *p = (size_in_bounds_p (size) ? malloc (size) : NULL);
4905436638acc7c010349a69c3395f1a57c642dc62Ying Wang*/
5005436638acc7c010349a69c3395f1a57c642dc62Ying Wang
5105436638acc7c010349a69c3395f1a57c642dc62Ying Wang/* Convert an arbitrary value >= 0 to type size_t.  */
5205436638acc7c010349a69c3395f1a57c642dc62Ying Wang#define xcast_size_t(N) \
5305436638acc7c010349a69c3395f1a57c642dc62Ying Wang  ((N) <= SIZE_MAX ? (size_t) (N) : SIZE_MAX)
5405436638acc7c010349a69c3395f1a57c642dc62Ying Wang
5505436638acc7c010349a69c3395f1a57c642dc62Ying Wang/* Sum of two sizes, with overflow check.  */
5605436638acc7c010349a69c3395f1a57c642dc62Ying WangXSIZE_INLINE size_t
5705436638acc7c010349a69c3395f1a57c642dc62Ying Wang#if __GNUC__ >= 3
5805436638acc7c010349a69c3395f1a57c642dc62Ying Wang__attribute__ ((__pure__))
5905436638acc7c010349a69c3395f1a57c642dc62Ying Wang#endif
6005436638acc7c010349a69c3395f1a57c642dc62Ying Wangxsum (size_t size1, size_t size2)
6105436638acc7c010349a69c3395f1a57c642dc62Ying Wang{
6205436638acc7c010349a69c3395f1a57c642dc62Ying Wang  size_t sum = size1 + size2;
6305436638acc7c010349a69c3395f1a57c642dc62Ying Wang  return (sum >= size1 ? sum : SIZE_MAX);
6405436638acc7c010349a69c3395f1a57c642dc62Ying Wang}
6505436638acc7c010349a69c3395f1a57c642dc62Ying Wang
6605436638acc7c010349a69c3395f1a57c642dc62Ying Wang/* Sum of three sizes, with overflow check.  */
6705436638acc7c010349a69c3395f1a57c642dc62Ying WangXSIZE_INLINE size_t
6805436638acc7c010349a69c3395f1a57c642dc62Ying Wang#if __GNUC__ >= 3
6905436638acc7c010349a69c3395f1a57c642dc62Ying Wang__attribute__ ((__pure__))
7005436638acc7c010349a69c3395f1a57c642dc62Ying Wang#endif
7105436638acc7c010349a69c3395f1a57c642dc62Ying Wangxsum3 (size_t size1, size_t size2, size_t size3)
7205436638acc7c010349a69c3395f1a57c642dc62Ying Wang{
7305436638acc7c010349a69c3395f1a57c642dc62Ying Wang  return xsum (xsum (size1, size2), size3);
7405436638acc7c010349a69c3395f1a57c642dc62Ying Wang}
7505436638acc7c010349a69c3395f1a57c642dc62Ying Wang
7605436638acc7c010349a69c3395f1a57c642dc62Ying Wang/* Sum of four sizes, with overflow check.  */
7705436638acc7c010349a69c3395f1a57c642dc62Ying WangXSIZE_INLINE size_t
7805436638acc7c010349a69c3395f1a57c642dc62Ying Wang#if __GNUC__ >= 3
7905436638acc7c010349a69c3395f1a57c642dc62Ying Wang__attribute__ ((__pure__))
8005436638acc7c010349a69c3395f1a57c642dc62Ying Wang#endif
8105436638acc7c010349a69c3395f1a57c642dc62Ying Wangxsum4 (size_t size1, size_t size2, size_t size3, size_t size4)
8205436638acc7c010349a69c3395f1a57c642dc62Ying Wang{
8305436638acc7c010349a69c3395f1a57c642dc62Ying Wang  return xsum (xsum (xsum (size1, size2), size3), size4);
8405436638acc7c010349a69c3395f1a57c642dc62Ying Wang}
8505436638acc7c010349a69c3395f1a57c642dc62Ying Wang
8605436638acc7c010349a69c3395f1a57c642dc62Ying Wang/* Maximum of two sizes, with overflow check.  */
8705436638acc7c010349a69c3395f1a57c642dc62Ying WangXSIZE_INLINE size_t
8805436638acc7c010349a69c3395f1a57c642dc62Ying Wang#if __GNUC__ >= 3
8905436638acc7c010349a69c3395f1a57c642dc62Ying Wang__attribute__ ((__pure__))
9005436638acc7c010349a69c3395f1a57c642dc62Ying Wang#endif
9105436638acc7c010349a69c3395f1a57c642dc62Ying Wangxmax (size_t size1, size_t size2)
9205436638acc7c010349a69c3395f1a57c642dc62Ying Wang{
9305436638acc7c010349a69c3395f1a57c642dc62Ying Wang  /* No explicit check is needed here, because for any n:
9405436638acc7c010349a69c3395f1a57c642dc62Ying Wang     max (SIZE_MAX, n) == SIZE_MAX and max (n, SIZE_MAX) == SIZE_MAX.  */
9505436638acc7c010349a69c3395f1a57c642dc62Ying Wang  return (size1 >= size2 ? size1 : size2);
9605436638acc7c010349a69c3395f1a57c642dc62Ying Wang}
9705436638acc7c010349a69c3395f1a57c642dc62Ying Wang
9805436638acc7c010349a69c3395f1a57c642dc62Ying Wang/* Multiplication of a count with an element size, with overflow check.
9905436638acc7c010349a69c3395f1a57c642dc62Ying Wang   The count must be >= 0 and the element size must be > 0.
10005436638acc7c010349a69c3395f1a57c642dc62Ying Wang   This is a macro, not a function, so that it works correctly even
10105436638acc7c010349a69c3395f1a57c642dc62Ying Wang   when N is of a wider type and N > SIZE_MAX.  */
10205436638acc7c010349a69c3395f1a57c642dc62Ying Wang#define xtimes(N, ELSIZE) \
10305436638acc7c010349a69c3395f1a57c642dc62Ying Wang  ((N) <= SIZE_MAX / (ELSIZE) ? (size_t) (N) * (ELSIZE) : SIZE_MAX)
10405436638acc7c010349a69c3395f1a57c642dc62Ying Wang
10505436638acc7c010349a69c3395f1a57c642dc62Ying Wang/* Check for overflow.  */
10605436638acc7c010349a69c3395f1a57c642dc62Ying Wang#define size_overflow_p(SIZE) \
10705436638acc7c010349a69c3395f1a57c642dc62Ying Wang  ((SIZE) == SIZE_MAX)
10805436638acc7c010349a69c3395f1a57c642dc62Ying Wang/* Check against overflow.  */
10905436638acc7c010349a69c3395f1a57c642dc62Ying Wang#define size_in_bounds_p(SIZE) \
11005436638acc7c010349a69c3395f1a57c642dc62Ying Wang  ((SIZE) != SIZE_MAX)
11105436638acc7c010349a69c3395f1a57c642dc62Ying Wang
11205436638acc7c010349a69c3395f1a57c642dc62Ying Wang_GL_INLINE_HEADER_END
11305436638acc7c010349a69c3395f1a57c642dc62Ying Wang
11405436638acc7c010349a69c3395f1a57c642dc62Ying Wang#endif /* _XSIZE_H */
115