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 40void *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 74FLAC__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 103FLAC__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 132FLAC__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 161FLAC__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 192FLAC__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