1/* alloc - Convenience routines for safely allocating memory 2 * Copyright (C) 2007-2009 Josh Coalson 3 * Copyright (C) 2011-2014 Xiph.Org Foundation 4 * 5 * Redistribution and use in source and binary forms, with or without 6 * modification, are permitted provided that the following conditions 7 * are met: 8 * 9 * - Redistributions of source code must retain the above copyright 10 * notice, this list of conditions and the following disclaimer. 11 * 12 * - Redistributions in binary form must reproduce the above copyright 13 * notice, this list of conditions and the following disclaimer in the 14 * documentation and/or other materials provided with the distribution. 15 * 16 * - Neither the name of the Xiph.org Foundation nor the names of its 17 * contributors may be used to endorse or promote products derived from 18 * this software without specific prior written permission. 19 * 20 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 21 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 22 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 23 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR 24 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, 25 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, 26 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR 27 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF 28 * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING 29 * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 30 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 31 */ 32 33#ifndef FLAC__SHARE__ALLOC_H 34#define FLAC__SHARE__ALLOC_H 35 36#ifdef HAVE_CONFIG_H 37# include <config.h> 38#endif 39 40/* WATCHOUT: for c++ you may have to #define __STDC_LIMIT_MACROS 1 real early 41 * before #including this file, otherwise SIZE_MAX might not be defined 42 */ 43 44#include <limits.h> /* for SIZE_MAX */ 45#if HAVE_STDINT_H 46#include <stdint.h> /* for SIZE_MAX in case limits.h didn't get it */ 47#endif 48#include <stdlib.h> /* for size_t, malloc(), etc */ 49#include "share/compat.h" 50 51#ifndef SIZE_MAX 52# ifndef SIZE_T_MAX 53# ifdef _MSC_VER 54# ifdef _WIN64 55# define SIZE_T_MAX 0xffffffffffffffffui64 56# else 57# define SIZE_T_MAX 0xffffffff 58# endif 59# else 60# error 61# endif 62# endif 63# define SIZE_MAX SIZE_T_MAX 64#endif 65 66/* avoid malloc()ing 0 bytes, see: 67 * https://www.securecoding.cert.org/confluence/display/seccode/MEM04-A.+Do+not+make+assumptions+about+the+result+of+allocating+0+bytes?focusedCommentId=5407003 68*/ 69static inline void *safe_malloc_(size_t size) 70{ 71 /* malloc(0) is undefined; FLAC src convention is to always allocate */ 72 if(!size) 73 size++; 74 return malloc(size); 75} 76 77static inline void *safe_calloc_(size_t nmemb, size_t size) 78{ 79 if(!nmemb || !size) 80 return malloc(1); /* malloc(0) is undefined; FLAC src convention is to always allocate */ 81 return calloc(nmemb, size); 82} 83 84/*@@@@ there's probably a better way to prevent overflows when allocating untrusted sums but this works for now */ 85 86static inline void *safe_malloc_add_2op_(size_t size1, size_t size2) 87{ 88 size2 += size1; 89 if(size2 < size1) 90 return 0; 91 return safe_malloc_(size2); 92} 93 94static inline void *safe_malloc_add_3op_(size_t size1, size_t size2, size_t size3) 95{ 96 size2 += size1; 97 if(size2 < size1) 98 return 0; 99 size3 += size2; 100 if(size3 < size2) 101 return 0; 102 return safe_malloc_(size3); 103} 104 105static inline void *safe_malloc_add_4op_(size_t size1, size_t size2, size_t size3, size_t size4) 106{ 107 size2 += size1; 108 if(size2 < size1) 109 return 0; 110 size3 += size2; 111 if(size3 < size2) 112 return 0; 113 size4 += size3; 114 if(size4 < size3) 115 return 0; 116 return safe_malloc_(size4); 117} 118 119void *safe_malloc_mul_2op_(size_t size1, size_t size2) ; 120 121static inline void *safe_malloc_mul_3op_(size_t size1, size_t size2, size_t size3) 122{ 123 if(!size1 || !size2 || !size3) 124 return malloc(1); /* malloc(0) is undefined; FLAC src convention is to always allocate */ 125 if(size1 > SIZE_MAX / size2) 126 return 0; 127 size1 *= size2; 128 if(size1 > SIZE_MAX / size3) 129 return 0; 130 return malloc(size1*size3); 131} 132 133/* size1*size2 + size3 */ 134static inline void *safe_malloc_mul2add_(size_t size1, size_t size2, size_t size3) 135{ 136 if(!size1 || !size2) 137 return safe_malloc_(size3); 138 if(size1 > SIZE_MAX / size2) 139 return 0; 140 return safe_malloc_add_2op_(size1*size2, size3); 141} 142 143/* size1 * (size2 + size3) */ 144static inline void *safe_malloc_muladd2_(size_t size1, size_t size2, size_t size3) 145{ 146 if(!size1 || (!size2 && !size3)) 147 return malloc(1); /* malloc(0) is undefined; FLAC src convention is to always allocate */ 148 size2 += size3; 149 if(size2 < size3) 150 return 0; 151 if(size1 > SIZE_MAX / size2) 152 return 0; 153 return malloc(size1*size2); 154} 155 156static inline void *safe_realloc_add_2op_(void *ptr, size_t size1, size_t size2) 157{ 158 size2 += size1; 159 if(size2 < size1) 160 return 0; 161 return realloc(ptr, size2); 162} 163 164static inline void *safe_realloc_add_3op_(void *ptr, size_t size1, size_t size2, size_t size3) 165{ 166 size2 += size1; 167 if(size2 < size1) 168 return 0; 169 size3 += size2; 170 if(size3 < size2) 171 return 0; 172 return realloc(ptr, size3); 173} 174 175static inline void *safe_realloc_add_4op_(void *ptr, size_t size1, size_t size2, size_t size3, size_t size4) 176{ 177 size2 += size1; 178 if(size2 < size1) 179 return 0; 180 size3 += size2; 181 if(size3 < size2) 182 return 0; 183 size4 += size3; 184 if(size4 < size3) 185 return 0; 186 return realloc(ptr, size4); 187} 188 189static inline void *safe_realloc_mul_2op_(void *ptr, size_t size1, size_t size2) 190{ 191 if(!size1 || !size2) 192 return realloc(ptr, 0); /* preserve POSIX realloc(ptr, 0) semantics */ 193 if(size1 > SIZE_MAX / size2) 194 return 0; 195 return realloc(ptr, size1*size2); 196} 197 198/* size1 * (size2 + size3) */ 199static inline void *safe_realloc_muladd2_(void *ptr, size_t size1, size_t size2, size_t size3) 200{ 201 if(!size1 || (!size2 && !size3)) 202 return realloc(ptr, 0); /* preserve POSIX realloc(ptr, 0) semantics */ 203 size2 += size3; 204 if(size2 < size3) 205 return 0; 206 return safe_realloc_mul_2op_(ptr, size1, size2); 207} 208 209#endif 210