Line data Source code
1 : /* xsize.h -- Checked size_t computations. 2 : 3 : Copyright (C) 2003, 2008-2025 Free Software Foundation, Inc. 4 : 5 : This file is free software: you can redistribute it and/or modify 6 : it under the terms of the GNU Lesser General Public License as 7 : published by the Free Software Foundation; either version 2.1 of the 8 : License, or (at your option) any later version. 9 : 10 : This file is distributed in the hope that it will be useful, 11 : but WITHOUT ANY WARRANTY; without even the implied warranty of 12 : MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 : GNU Lesser General Public License for more details. 14 : 15 : You should have received a copy of the GNU Lesser General Public License 16 : along with this program. If not, see <https://www.gnu.org/licenses/>. */ 17 : 18 : #ifndef _XSIZE_H 19 : #define _XSIZE_H 20 : 21 : /* This file uses _GL_INLINE_HEADER_BEGIN, _GL_INLINE, HAVE_STDINT_H. */ 22 : #if !_GL_CONFIG_H_INCLUDED 23 : #error "Please include config.h first." 24 : #endif 25 : 26 : /* Get size_t. */ 27 : #include <stddef.h> 28 : 29 : /* Get INT_MAX, SIZE_MAX. */ 30 : #include <limits.h> 31 : #if HAVE_STDINT_H 32 : # include <stdint.h> 33 : #endif 34 : 35 : /* Get ATTRIBUTE_PURE. */ 36 : #include "attribute.h" 37 : 38 : _GL_INLINE_HEADER_BEGIN 39 : #ifndef XSIZE_INLINE 40 : # define XSIZE_INLINE _GL_INLINE 41 : #endif 42 : 43 : #ifdef __cplusplus 44 : extern "C" { 45 : #endif 46 : 47 : 48 : /* The size of memory objects is often computed through expressions of 49 : type size_t. Example: 50 : void* p = malloc (header_size + n * element_size). 51 : These computations can lead to overflow. When this happens, malloc() 52 : returns a piece of memory that is way too small, and the program then 53 : crashes while attempting to fill the memory. 54 : To avoid this, the functions and macros in this file check for overflow. 55 : The convention is that SIZE_MAX represents overflow. 56 : malloc (SIZE_MAX) is not guaranteed to fail -- think of a malloc 57 : implementation that uses mmap --, it's recommended to use size_overflow_p() 58 : or size_in_bounds_p() before invoking malloc(). 59 : The example thus becomes: 60 : size_t size = xsum (header_size, xtimes (n, element_size)); 61 : void *p = (size_in_bounds_p (size) ? malloc (size) : NULL); 62 : */ 63 : 64 : /* Convert an arbitrary N >= 0 to type size_t. 65 : N should not have side effects. */ 66 : #define xcast_size_t(N) \ 67 : ((N) <= SIZE_MAX ? (size_t) (N) : SIZE_MAX) 68 : 69 : /* Sum of two sizes, with overflow check. */ 70 : XSIZE_INLINE size_t ATTRIBUTE_PURE 71 91073 : xsum (size_t size1, size_t size2) 72 : { 73 : if (INT_MAX < SIZE_MAX) 74 : { 75 : /* Optimize for the common case where size_t arithmetic wraps 76 : around without undefined behavior. */ 77 91073 : size_t sum = size1 + size2; 78 91073 : return size1 <= sum ? sum : SIZE_MAX; 79 : } 80 : 81 : return size1 <= SIZE_MAX - size2 ? size1 + size2 : SIZE_MAX; 82 : } 83 : 84 : /* Sum of three sizes, with overflow check. */ 85 : XSIZE_INLINE size_t ATTRIBUTE_PURE 86 0 : xsum3 (size_t size1, size_t size2, size_t size3) 87 : { 88 0 : return xsum (xsum (size1, size2), size3); 89 : } 90 : 91 : /* Sum of four sizes, with overflow check. */ 92 : XSIZE_INLINE size_t ATTRIBUTE_PURE 93 14391 : xsum4 (size_t size1, size_t size2, size_t size3, size_t size4) 94 : { 95 14391 : return xsum (xsum (xsum (size1, size2), size3), size4); 96 : } 97 : 98 : /* Maximum of two sizes, with overflow check. */ 99 : XSIZE_INLINE size_t ATTRIBUTE_PURE 100 0 : xmax (size_t size1, size_t size2) 101 : { 102 : /* No explicit check is needed here, because for any n: 103 : max (SIZE_MAX, n) == SIZE_MAX and max (n, SIZE_MAX) == SIZE_MAX. */ 104 0 : return (size1 >= size2 ? size1 : size2); 105 : } 106 : 107 : /* Multiplication of a count with an element size, with overflow check. 108 : The count must be >= 0 and the element size must be > 0. 109 : Arguments should not have side effects. 110 : The element size's type should be no wider than size_t. 111 : This is a macro, not a function, so that it works correctly even 112 : when N is of a wider type and N > SIZE_MAX. */ 113 : #define xtimes(N, ELSIZE) \ 114 : ((N) <= SIZE_MAX / (ELSIZE) ? (size_t) (N) * (ELSIZE) : SIZE_MAX) 115 : 116 : /* Check for overflow. */ 117 : #define size_overflow_p(SIZE) \ 118 : ((SIZE) == SIZE_MAX) 119 : /* Check against overflow. */ 120 : #define size_in_bounds_p(SIZE) \ 121 : ((SIZE) != SIZE_MAX) 122 : 123 : 124 : #ifdef __cplusplus 125 : } 126 : #endif 127 : 128 : _GL_INLINE_HEADER_END 129 : 130 : #endif /* _XSIZE_H */