1 /* libFLAC - Free Lossless Audio Codec library 2 * Copyright (C) 2001,2002,2003,2004,2005,2006,2007 Josh Coalson 3 * 4 * Redistribution and use in source and binary forms, with or without 5 * modification, are permitted provided that the following conditions 6 * are met: 7 * 8 * - Redistributions of source code must retain the above copyright 9 * notice, this list of conditions and the following disclaimer. 10 * 11 * - Redistributions in binary form must reproduce the above copyright 12 * notice, this list of conditions and the following disclaimer in the 13 * documentation and/or other materials provided with the distribution. 14 * 15 * - Neither the name of the Xiph.org Foundation nor the names of its 16 * contributors may be used to endorse or promote products derived from 17 * this software without specific prior written permission. 18 * 19 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 20 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 21 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 22 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR 23 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, 24 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, 25 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR 26 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF 27 * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING 28 * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 29 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 30 */ 31 32 #if HAVE_CONFIG_H 33 # include <config.h> 34 #endif 35 36 #include "private/memory.h" 37 #include "FLAC/assert.h" 38 #include "share/alloc.h" 39 40 void *FLAC__memory_alloc_aligned(size_t bytes, void **aligned_address) 41 { 42 void *x; 43 44 FLAC__ASSERT(0 != aligned_address); 45 46 #ifdef FLAC__ALIGN_MALLOC_DATA 47 /* align on 32-byte (256-bit) boundary */ 48 x = safe_malloc_add_2op_(bytes, /*+*/31); 49 #ifdef SIZEOF_VOIDP 50 #if SIZEOF_VOIDP == 4 51 /* could do *aligned_address = x + ((unsigned) (32 - (((unsigned)x) & 31))) & 31; */ 52 *aligned_address = (void*)(((unsigned)x + 31) & -32); 53 #elif SIZEOF_VOIDP == 8 54 *aligned_address = (void*)(((FLAC__uint64)x + 31) & (FLAC__uint64)(-((FLAC__int64)32))); 55 #else 56 # error Unsupported sizeof(void*) 57 #endif 58 #else 59 /* there's got to be a better way to do this right for all archs */ 60 if(sizeof(void*) == sizeof(unsigned)) 61 *aligned_address = (void*)(((unsigned)x + 31) & -32); 62 else if(sizeof(void*) == sizeof(FLAC__uint64)) 63 *aligned_address = (void*)(((FLAC__uint64)x + 31) & (FLAC__uint64)(-((FLAC__int64)32))); 64 else 65 return 0; 66 #endif 67 #else 68 x = safe_malloc_(bytes); 69 *aligned_address = x; 70 #endif 71 return x; 72 } 73 74 FLAC__bool FLAC__memory_alloc_aligned_int32_array(unsigned elements, FLAC__int32 **unaligned_pointer, FLAC__int32 **aligned_pointer) 75 { 76 FLAC__int32 *pu; /* unaligned pointer */ 77 union { /* union needed to comply with C99 pointer aliasing rules */ 78 FLAC__int32 *pa; /* aligned pointer */ 79 void *pv; /* aligned pointer alias */ 80 } u; 81 82 FLAC__ASSERT(elements > 0); 83 FLAC__ASSERT(0 != unaligned_pointer); 84 FLAC__ASSERT(0 != aligned_pointer); 85 FLAC__ASSERT(unaligned_pointer != aligned_pointer); 86 87 if((size_t)elements > SIZE_MAX / sizeof(*pu)) /* overflow check */ 88 return false; 89 90 pu = (FLAC__int32*)FLAC__memory_alloc_aligned(sizeof(*pu) * (size_t)elements, &u.pv); 91 if(0 == pu) { 92 return false; 93 } 94 else { 95 if(*unaligned_pointer != 0) 96 free(*unaligned_pointer); 97 *unaligned_pointer = pu; 98 *aligned_pointer = u.pa; 99 return true; 100 } 101 } 102 103 FLAC__bool FLAC__memory_alloc_aligned_uint32_array(unsigned elements, FLAC__uint32 **unaligned_pointer, FLAC__uint32 **aligned_pointer) 104 { 105 FLAC__uint32 *pu; /* unaligned pointer */ 106 union { /* union needed to comply with C99 pointer aliasing rules */ 107 FLAC__uint32 *pa; /* aligned pointer */ 108 void *pv; /* aligned pointer alias */ 109 } u; 110 111 FLAC__ASSERT(elements > 0); 112 FLAC__ASSERT(0 != unaligned_pointer); 113 FLAC__ASSERT(0 != aligned_pointer); 114 FLAC__ASSERT(unaligned_pointer != aligned_pointer); 115 116 if((size_t)elements > SIZE_MAX / sizeof(*pu)) /* overflow check */ 117 return false; 118 119 pu = (FLAC__uint32*)FLAC__memory_alloc_aligned(sizeof(*pu) * elements, &u.pv); 120 if(0 == pu) { 121 return false; 122 } 123 else { 124 if(*unaligned_pointer != 0) 125 free(*unaligned_pointer); 126 *unaligned_pointer = pu; 127 *aligned_pointer = u.pa; 128 return true; 129 } 130 } 131 132 FLAC__bool FLAC__memory_alloc_aligned_uint64_array(unsigned elements, FLAC__uint64 **unaligned_pointer, FLAC__uint64 **aligned_pointer) 133 { 134 FLAC__uint64 *pu; /* unaligned pointer */ 135 union { /* union needed to comply with C99 pointer aliasing rules */ 136 FLAC__uint64 *pa; /* aligned pointer */ 137 void *pv; /* aligned pointer alias */ 138 } u; 139 140 FLAC__ASSERT(elements > 0); 141 FLAC__ASSERT(0 != unaligned_pointer); 142 FLAC__ASSERT(0 != aligned_pointer); 143 FLAC__ASSERT(unaligned_pointer != aligned_pointer); 144 145 if((size_t)elements > SIZE_MAX / sizeof(*pu)) /* overflow check */ 146 return false; 147 148 pu = (FLAC__uint64*)FLAC__memory_alloc_aligned(sizeof(*pu) * elements, &u.pv); 149 if(0 == pu) { 150 return false; 151 } 152 else { 153 if(*unaligned_pointer != 0) 154 free(*unaligned_pointer); 155 *unaligned_pointer = pu; 156 *aligned_pointer = u.pa; 157 return true; 158 } 159 } 160 161 FLAC__bool FLAC__memory_alloc_aligned_unsigned_array(unsigned elements, unsigned **unaligned_pointer, unsigned **aligned_pointer) 162 { 163 unsigned *pu; /* unaligned pointer */ 164 union { /* union needed to comply with C99 pointer aliasing rules */ 165 unsigned *pa; /* aligned pointer */ 166 void *pv; /* aligned pointer alias */ 167 } u; 168 169 FLAC__ASSERT(elements > 0); 170 FLAC__ASSERT(0 != unaligned_pointer); 171 FLAC__ASSERT(0 != aligned_pointer); 172 FLAC__ASSERT(unaligned_pointer != aligned_pointer); 173 174 if((size_t)elements > SIZE_MAX / sizeof(*pu)) /* overflow check */ 175 return false; 176 177 pu = (unsigned*)FLAC__memory_alloc_aligned(sizeof(*pu) * elements, &u.pv); 178 if(0 == pu) { 179 return false; 180 } 181 else { 182 if(*unaligned_pointer != 0) 183 free(*unaligned_pointer); 184 *unaligned_pointer = pu; 185 *aligned_pointer = u.pa; 186 return true; 187 } 188 } 189 190 #ifndef FLAC__INTEGER_ONLY_LIBRARY 191 192 FLAC__bool FLAC__memory_alloc_aligned_real_array(unsigned elements, FLAC__real **unaligned_pointer, FLAC__real **aligned_pointer) 193 { 194 FLAC__real *pu; /* unaligned pointer */ 195 union { /* union needed to comply with C99 pointer aliasing rules */ 196 FLAC__real *pa; /* aligned pointer */ 197 void *pv; /* aligned pointer alias */ 198 } u; 199 200 FLAC__ASSERT(elements > 0); 201 FLAC__ASSERT(0 != unaligned_pointer); 202 FLAC__ASSERT(0 != aligned_pointer); 203 FLAC__ASSERT(unaligned_pointer != aligned_pointer); 204 205 if((size_t)elements > SIZE_MAX / sizeof(*pu)) /* overflow check */ 206 return false; 207 208 pu = (FLAC__real*)FLAC__memory_alloc_aligned(sizeof(*pu) * elements, &u.pv); 209 if(0 == pu) { 210 return false; 211 } 212 else { 213 if(*unaligned_pointer != 0) 214 free(*unaligned_pointer); 215 *unaligned_pointer = pu; 216 *aligned_pointer = u.pa; 217 return true; 218 } 219 } 220 221 #endif 222