131e4f3166a91a2ebb34f643787122a638d9f1471Robert Shih/* alloc - Convenience routines for safely allocating memory 231e4f3166a91a2ebb34f643787122a638d9f1471Robert Shih * Copyright (C) 2007-2009 Josh Coalson 331e4f3166a91a2ebb34f643787122a638d9f1471Robert Shih * Copyright (C) 2011-2014 Xiph.Org Foundation 4c74663799493f2b1e6123c18def94295d0afab7Kenny Root * 531e4f3166a91a2ebb34f643787122a638d9f1471Robert Shih * Redistribution and use in source and binary forms, with or without 631e4f3166a91a2ebb34f643787122a638d9f1471Robert Shih * modification, are permitted provided that the following conditions 731e4f3166a91a2ebb34f643787122a638d9f1471Robert Shih * are met: 8c74663799493f2b1e6123c18def94295d0afab7Kenny Root * 931e4f3166a91a2ebb34f643787122a638d9f1471Robert Shih * - Redistributions of source code must retain the above copyright 1031e4f3166a91a2ebb34f643787122a638d9f1471Robert Shih * notice, this list of conditions and the following disclaimer. 11c74663799493f2b1e6123c18def94295d0afab7Kenny Root * 1231e4f3166a91a2ebb34f643787122a638d9f1471Robert Shih * - Redistributions in binary form must reproduce the above copyright 1331e4f3166a91a2ebb34f643787122a638d9f1471Robert Shih * notice, this list of conditions and the following disclaimer in the 1431e4f3166a91a2ebb34f643787122a638d9f1471Robert Shih * documentation and/or other materials provided with the distribution. 1531e4f3166a91a2ebb34f643787122a638d9f1471Robert Shih * 1631e4f3166a91a2ebb34f643787122a638d9f1471Robert Shih * - Neither the name of the Xiph.org Foundation nor the names of its 1731e4f3166a91a2ebb34f643787122a638d9f1471Robert Shih * contributors may be used to endorse or promote products derived from 1831e4f3166a91a2ebb34f643787122a638d9f1471Robert Shih * this software without specific prior written permission. 1931e4f3166a91a2ebb34f643787122a638d9f1471Robert Shih * 2031e4f3166a91a2ebb34f643787122a638d9f1471Robert Shih * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 2131e4f3166a91a2ebb34f643787122a638d9f1471Robert Shih * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 2231e4f3166a91a2ebb34f643787122a638d9f1471Robert Shih * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 2331e4f3166a91a2ebb34f643787122a638d9f1471Robert Shih * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR 2431e4f3166a91a2ebb34f643787122a638d9f1471Robert Shih * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, 2531e4f3166a91a2ebb34f643787122a638d9f1471Robert Shih * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, 2631e4f3166a91a2ebb34f643787122a638d9f1471Robert Shih * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR 2731e4f3166a91a2ebb34f643787122a638d9f1471Robert Shih * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF 2831e4f3166a91a2ebb34f643787122a638d9f1471Robert Shih * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING 2931e4f3166a91a2ebb34f643787122a638d9f1471Robert Shih * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 3031e4f3166a91a2ebb34f643787122a638d9f1471Robert Shih * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 3131e4f3166a91a2ebb34f643787122a638d9f1471Robert Shih */ 3231e4f3166a91a2ebb34f643787122a638d9f1471Robert Shih 3331e4f3166a91a2ebb34f643787122a638d9f1471Robert Shih#ifndef FLAC__SHARE__ALLOC_H 3431e4f3166a91a2ebb34f643787122a638d9f1471Robert Shih#define FLAC__SHARE__ALLOC_H 3531e4f3166a91a2ebb34f643787122a638d9f1471Robert Shih 3631e4f3166a91a2ebb34f643787122a638d9f1471Robert Shih#ifdef HAVE_CONFIG_H 3731e4f3166a91a2ebb34f643787122a638d9f1471Robert Shih# include <config.h> 3831e4f3166a91a2ebb34f643787122a638d9f1471Robert Shih#endif 3931e4f3166a91a2ebb34f643787122a638d9f1471Robert Shih 4031e4f3166a91a2ebb34f643787122a638d9f1471Robert Shih/* WATCHOUT: for c++ you may have to #define __STDC_LIMIT_MACROS 1 real early 4131e4f3166a91a2ebb34f643787122a638d9f1471Robert Shih * before #including this file, otherwise SIZE_MAX might not be defined 42c74663799493f2b1e6123c18def94295d0afab7Kenny Root */ 43c74663799493f2b1e6123c18def94295d0afab7Kenny Root 4431e4f3166a91a2ebb34f643787122a638d9f1471Robert Shih#include <limits.h> /* for SIZE_MAX */ 4531e4f3166a91a2ebb34f643787122a638d9f1471Robert Shih#if HAVE_STDINT_H 4631e4f3166a91a2ebb34f643787122a638d9f1471Robert Shih#include <stdint.h> /* for SIZE_MAX in case limits.h didn't get it */ 4731e4f3166a91a2ebb34f643787122a638d9f1471Robert Shih#endif 4831e4f3166a91a2ebb34f643787122a638d9f1471Robert Shih#include <stdlib.h> /* for size_t, malloc(), etc */ 4931e4f3166a91a2ebb34f643787122a638d9f1471Robert Shih#include "share/compat.h" 50c74663799493f2b1e6123c18def94295d0afab7Kenny Root 5131e4f3166a91a2ebb34f643787122a638d9f1471Robert Shih#ifndef SIZE_MAX 5231e4f3166a91a2ebb34f643787122a638d9f1471Robert Shih# ifndef SIZE_T_MAX 5331e4f3166a91a2ebb34f643787122a638d9f1471Robert Shih# ifdef _MSC_VER 5431e4f3166a91a2ebb34f643787122a638d9f1471Robert Shih# ifdef _WIN64 5531e4f3166a91a2ebb34f643787122a638d9f1471Robert Shih# define SIZE_T_MAX 0xffffffffffffffffui64 5631e4f3166a91a2ebb34f643787122a638d9f1471Robert Shih# else 5731e4f3166a91a2ebb34f643787122a638d9f1471Robert Shih# define SIZE_T_MAX 0xffffffff 5831e4f3166a91a2ebb34f643787122a638d9f1471Robert Shih# endif 5931e4f3166a91a2ebb34f643787122a638d9f1471Robert Shih# else 6031e4f3166a91a2ebb34f643787122a638d9f1471Robert Shih# error 6131e4f3166a91a2ebb34f643787122a638d9f1471Robert Shih# endif 6231e4f3166a91a2ebb34f643787122a638d9f1471Robert Shih# endif 6331e4f3166a91a2ebb34f643787122a638d9f1471Robert Shih# define SIZE_MAX SIZE_T_MAX 6431e4f3166a91a2ebb34f643787122a638d9f1471Robert Shih#endif 6531e4f3166a91a2ebb34f643787122a638d9f1471Robert Shih 6631e4f3166a91a2ebb34f643787122a638d9f1471Robert Shih/* avoid malloc()ing 0 bytes, see: 6731e4f3166a91a2ebb34f643787122a638d9f1471Robert Shih * https://www.securecoding.cert.org/confluence/display/seccode/MEM04-A.+Do+not+make+assumptions+about+the+result+of+allocating+0+bytes?focusedCommentId=5407003 6831e4f3166a91a2ebb34f643787122a638d9f1471Robert Shih*/ 6931e4f3166a91a2ebb34f643787122a638d9f1471Robert Shihstatic inline void *safe_malloc_(size_t size) 7031e4f3166a91a2ebb34f643787122a638d9f1471Robert Shih{ 7131e4f3166a91a2ebb34f643787122a638d9f1471Robert Shih /* malloc(0) is undefined; FLAC src convention is to always allocate */ 7231e4f3166a91a2ebb34f643787122a638d9f1471Robert Shih if(!size) 7331e4f3166a91a2ebb34f643787122a638d9f1471Robert Shih size++; 7431e4f3166a91a2ebb34f643787122a638d9f1471Robert Shih return malloc(size); 7531e4f3166a91a2ebb34f643787122a638d9f1471Robert Shih} 7631e4f3166a91a2ebb34f643787122a638d9f1471Robert Shih 7731e4f3166a91a2ebb34f643787122a638d9f1471Robert Shihstatic inline void *safe_calloc_(size_t nmemb, size_t size) 7831e4f3166a91a2ebb34f643787122a638d9f1471Robert Shih{ 7931e4f3166a91a2ebb34f643787122a638d9f1471Robert Shih if(!nmemb || !size) 8031e4f3166a91a2ebb34f643787122a638d9f1471Robert Shih return malloc(1); /* malloc(0) is undefined; FLAC src convention is to always allocate */ 8131e4f3166a91a2ebb34f643787122a638d9f1471Robert Shih return calloc(nmemb, size); 8231e4f3166a91a2ebb34f643787122a638d9f1471Robert Shih} 8331e4f3166a91a2ebb34f643787122a638d9f1471Robert Shih 8431e4f3166a91a2ebb34f643787122a638d9f1471Robert Shih/*@@@@ there's probably a better way to prevent overflows when allocating untrusted sums but this works for now */ 8531e4f3166a91a2ebb34f643787122a638d9f1471Robert Shih 8631e4f3166a91a2ebb34f643787122a638d9f1471Robert Shihstatic inline void *safe_malloc_add_2op_(size_t size1, size_t size2) 8731e4f3166a91a2ebb34f643787122a638d9f1471Robert Shih{ 8831e4f3166a91a2ebb34f643787122a638d9f1471Robert Shih size2 += size1; 8931e4f3166a91a2ebb34f643787122a638d9f1471Robert Shih if(size2 < size1) 9031e4f3166a91a2ebb34f643787122a638d9f1471Robert Shih return 0; 9131e4f3166a91a2ebb34f643787122a638d9f1471Robert Shih return safe_malloc_(size2); 9231e4f3166a91a2ebb34f643787122a638d9f1471Robert Shih} 9331e4f3166a91a2ebb34f643787122a638d9f1471Robert Shih 9431e4f3166a91a2ebb34f643787122a638d9f1471Robert Shihstatic inline void *safe_malloc_add_3op_(size_t size1, size_t size2, size_t size3) 9531e4f3166a91a2ebb34f643787122a638d9f1471Robert Shih{ 9631e4f3166a91a2ebb34f643787122a638d9f1471Robert Shih size2 += size1; 9731e4f3166a91a2ebb34f643787122a638d9f1471Robert Shih if(size2 < size1) 9831e4f3166a91a2ebb34f643787122a638d9f1471Robert Shih return 0; 9931e4f3166a91a2ebb34f643787122a638d9f1471Robert Shih size3 += size2; 10031e4f3166a91a2ebb34f643787122a638d9f1471Robert Shih if(size3 < size2) 10131e4f3166a91a2ebb34f643787122a638d9f1471Robert Shih return 0; 10231e4f3166a91a2ebb34f643787122a638d9f1471Robert Shih return safe_malloc_(size3); 10331e4f3166a91a2ebb34f643787122a638d9f1471Robert Shih} 10431e4f3166a91a2ebb34f643787122a638d9f1471Robert Shih 10531e4f3166a91a2ebb34f643787122a638d9f1471Robert Shihstatic inline void *safe_malloc_add_4op_(size_t size1, size_t size2, size_t size3, size_t size4) 10631e4f3166a91a2ebb34f643787122a638d9f1471Robert Shih{ 10731e4f3166a91a2ebb34f643787122a638d9f1471Robert Shih size2 += size1; 10831e4f3166a91a2ebb34f643787122a638d9f1471Robert Shih if(size2 < size1) 10931e4f3166a91a2ebb34f643787122a638d9f1471Robert Shih return 0; 11031e4f3166a91a2ebb34f643787122a638d9f1471Robert Shih size3 += size2; 11131e4f3166a91a2ebb34f643787122a638d9f1471Robert Shih if(size3 < size2) 11231e4f3166a91a2ebb34f643787122a638d9f1471Robert Shih return 0; 11331e4f3166a91a2ebb34f643787122a638d9f1471Robert Shih size4 += size3; 11431e4f3166a91a2ebb34f643787122a638d9f1471Robert Shih if(size4 < size3) 11531e4f3166a91a2ebb34f643787122a638d9f1471Robert Shih return 0; 11631e4f3166a91a2ebb34f643787122a638d9f1471Robert Shih return safe_malloc_(size4); 11731e4f3166a91a2ebb34f643787122a638d9f1471Robert Shih} 11831e4f3166a91a2ebb34f643787122a638d9f1471Robert Shih 11931e4f3166a91a2ebb34f643787122a638d9f1471Robert Shihvoid *safe_malloc_mul_2op_(size_t size1, size_t size2) ; 12031e4f3166a91a2ebb34f643787122a638d9f1471Robert Shih 12131e4f3166a91a2ebb34f643787122a638d9f1471Robert Shihstatic inline void *safe_malloc_mul_3op_(size_t size1, size_t size2, size_t size3) 12231e4f3166a91a2ebb34f643787122a638d9f1471Robert Shih{ 12331e4f3166a91a2ebb34f643787122a638d9f1471Robert Shih if(!size1 || !size2 || !size3) 12431e4f3166a91a2ebb34f643787122a638d9f1471Robert Shih return malloc(1); /* malloc(0) is undefined; FLAC src convention is to always allocate */ 12531e4f3166a91a2ebb34f643787122a638d9f1471Robert Shih if(size1 > SIZE_MAX / size2) 12631e4f3166a91a2ebb34f643787122a638d9f1471Robert Shih return 0; 12731e4f3166a91a2ebb34f643787122a638d9f1471Robert Shih size1 *= size2; 12831e4f3166a91a2ebb34f643787122a638d9f1471Robert Shih if(size1 > SIZE_MAX / size3) 12931e4f3166a91a2ebb34f643787122a638d9f1471Robert Shih return 0; 13031e4f3166a91a2ebb34f643787122a638d9f1471Robert Shih return malloc(size1*size3); 13131e4f3166a91a2ebb34f643787122a638d9f1471Robert Shih} 13231e4f3166a91a2ebb34f643787122a638d9f1471Robert Shih 13331e4f3166a91a2ebb34f643787122a638d9f1471Robert Shih/* size1*size2 + size3 */ 13431e4f3166a91a2ebb34f643787122a638d9f1471Robert Shihstatic inline void *safe_malloc_mul2add_(size_t size1, size_t size2, size_t size3) 13531e4f3166a91a2ebb34f643787122a638d9f1471Robert Shih{ 13631e4f3166a91a2ebb34f643787122a638d9f1471Robert Shih if(!size1 || !size2) 13731e4f3166a91a2ebb34f643787122a638d9f1471Robert Shih return safe_malloc_(size3); 13831e4f3166a91a2ebb34f643787122a638d9f1471Robert Shih if(size1 > SIZE_MAX / size2) 13931e4f3166a91a2ebb34f643787122a638d9f1471Robert Shih return 0; 14031e4f3166a91a2ebb34f643787122a638d9f1471Robert Shih return safe_malloc_add_2op_(size1*size2, size3); 14131e4f3166a91a2ebb34f643787122a638d9f1471Robert Shih} 142c74663799493f2b1e6123c18def94295d0afab7Kenny Root 14331e4f3166a91a2ebb34f643787122a638d9f1471Robert Shih/* size1 * (size2 + size3) */ 14431e4f3166a91a2ebb34f643787122a638d9f1471Robert Shihstatic inline void *safe_malloc_muladd2_(size_t size1, size_t size2, size_t size3) 145c74663799493f2b1e6123c18def94295d0afab7Kenny Root{ 14631e4f3166a91a2ebb34f643787122a638d9f1471Robert Shih if(!size1 || (!size2 && !size3)) 14731e4f3166a91a2ebb34f643787122a638d9f1471Robert Shih return malloc(1); /* malloc(0) is undefined; FLAC src convention is to always allocate */ 14831e4f3166a91a2ebb34f643787122a638d9f1471Robert Shih size2 += size3; 14931e4f3166a91a2ebb34f643787122a638d9f1471Robert Shih if(size2 < size3) 15031e4f3166a91a2ebb34f643787122a638d9f1471Robert Shih return 0; 15131e4f3166a91a2ebb34f643787122a638d9f1471Robert Shih if(size1 > SIZE_MAX / size2) 15231e4f3166a91a2ebb34f643787122a638d9f1471Robert Shih return 0; 15331e4f3166a91a2ebb34f643787122a638d9f1471Robert Shih return malloc(size1*size2); 154c74663799493f2b1e6123c18def94295d0afab7Kenny Root} 155c74663799493f2b1e6123c18def94295d0afab7Kenny Root 15631e4f3166a91a2ebb34f643787122a638d9f1471Robert Shihstatic inline void *safe_realloc_add_2op_(void *ptr, size_t size1, size_t size2) 157c74663799493f2b1e6123c18def94295d0afab7Kenny Root{ 15831e4f3166a91a2ebb34f643787122a638d9f1471Robert Shih size2 += size1; 15931e4f3166a91a2ebb34f643787122a638d9f1471Robert Shih if(size2 < size1) 16031e4f3166a91a2ebb34f643787122a638d9f1471Robert Shih return 0; 16131e4f3166a91a2ebb34f643787122a638d9f1471Robert Shih return realloc(ptr, size2); 162c74663799493f2b1e6123c18def94295d0afab7Kenny Root} 163c74663799493f2b1e6123c18def94295d0afab7Kenny Root 16431e4f3166a91a2ebb34f643787122a638d9f1471Robert Shihstatic inline void *safe_realloc_add_3op_(void *ptr, size_t size1, size_t size2, size_t size3) 165c74663799493f2b1e6123c18def94295d0afab7Kenny Root{ 16631e4f3166a91a2ebb34f643787122a638d9f1471Robert Shih size2 += size1; 16731e4f3166a91a2ebb34f643787122a638d9f1471Robert Shih if(size2 < size1) 16831e4f3166a91a2ebb34f643787122a638d9f1471Robert Shih return 0; 16931e4f3166a91a2ebb34f643787122a638d9f1471Robert Shih size3 += size2; 17031e4f3166a91a2ebb34f643787122a638d9f1471Robert Shih if(size3 < size2) 17131e4f3166a91a2ebb34f643787122a638d9f1471Robert Shih return 0; 17231e4f3166a91a2ebb34f643787122a638d9f1471Robert Shih return realloc(ptr, size3); 173c74663799493f2b1e6123c18def94295d0afab7Kenny Root} 174c74663799493f2b1e6123c18def94295d0afab7Kenny Root 17531e4f3166a91a2ebb34f643787122a638d9f1471Robert Shihstatic inline void *safe_realloc_add_4op_(void *ptr, size_t size1, size_t size2, size_t size3, size_t size4) 176c74663799493f2b1e6123c18def94295d0afab7Kenny Root{ 17731e4f3166a91a2ebb34f643787122a638d9f1471Robert Shih size2 += size1; 17831e4f3166a91a2ebb34f643787122a638d9f1471Robert Shih if(size2 < size1) 17931e4f3166a91a2ebb34f643787122a638d9f1471Robert Shih return 0; 18031e4f3166a91a2ebb34f643787122a638d9f1471Robert Shih size3 += size2; 18131e4f3166a91a2ebb34f643787122a638d9f1471Robert Shih if(size3 < size2) 18231e4f3166a91a2ebb34f643787122a638d9f1471Robert Shih return 0; 18331e4f3166a91a2ebb34f643787122a638d9f1471Robert Shih size4 += size3; 18431e4f3166a91a2ebb34f643787122a638d9f1471Robert Shih if(size4 < size3) 18531e4f3166a91a2ebb34f643787122a638d9f1471Robert Shih return 0; 18631e4f3166a91a2ebb34f643787122a638d9f1471Robert Shih return realloc(ptr, size4); 187c74663799493f2b1e6123c18def94295d0afab7Kenny Root} 188c74663799493f2b1e6123c18def94295d0afab7Kenny Root 18931e4f3166a91a2ebb34f643787122a638d9f1471Robert Shihstatic inline void *safe_realloc_mul_2op_(void *ptr, size_t size1, size_t size2) 190c74663799493f2b1e6123c18def94295d0afab7Kenny Root{ 19131e4f3166a91a2ebb34f643787122a638d9f1471Robert Shih if(!size1 || !size2) 19231e4f3166a91a2ebb34f643787122a638d9f1471Robert Shih return realloc(ptr, 0); /* preserve POSIX realloc(ptr, 0) semantics */ 19331e4f3166a91a2ebb34f643787122a638d9f1471Robert Shih if(size1 > SIZE_MAX / size2) 19431e4f3166a91a2ebb34f643787122a638d9f1471Robert Shih return 0; 19531e4f3166a91a2ebb34f643787122a638d9f1471Robert Shih return realloc(ptr, size1*size2); 196c74663799493f2b1e6123c18def94295d0afab7Kenny Root} 197c74663799493f2b1e6123c18def94295d0afab7Kenny Root 19831e4f3166a91a2ebb34f643787122a638d9f1471Robert Shih/* size1 * (size2 + size3) */ 19931e4f3166a91a2ebb34f643787122a638d9f1471Robert Shihstatic inline void *safe_realloc_muladd2_(void *ptr, size_t size1, size_t size2, size_t size3) 200c74663799493f2b1e6123c18def94295d0afab7Kenny Root{ 20131e4f3166a91a2ebb34f643787122a638d9f1471Robert Shih if(!size1 || (!size2 && !size3)) 20231e4f3166a91a2ebb34f643787122a638d9f1471Robert Shih return realloc(ptr, 0); /* preserve POSIX realloc(ptr, 0) semantics */ 20331e4f3166a91a2ebb34f643787122a638d9f1471Robert Shih size2 += size3; 20431e4f3166a91a2ebb34f643787122a638d9f1471Robert Shih if(size2 < size3) 20531e4f3166a91a2ebb34f643787122a638d9f1471Robert Shih return 0; 20631e4f3166a91a2ebb34f643787122a638d9f1471Robert Shih return safe_realloc_mul_2op_(ptr, size1, size2); 207c74663799493f2b1e6123c18def94295d0afab7Kenny Root} 208c74663799493f2b1e6123c18def94295d0afab7Kenny Root 20931e4f3166a91a2ebb34f643787122a638d9f1471Robert Shih#endif 210