Set version to 1.3.0 and update coyprights throughout.
[platform/upstream/flac.git] / src / libFLAC / memory.c
1 /* libFLAC - Free Lossless Audio Codec library
2  * Copyright (C) 2001-2009  Josh Coalson
3  * Copyright (C) 2011-2013  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 #if HAVE_CONFIG_H
34 #  include <config.h>
35 #endif
36
37 #include "private/memory.h"
38 #include "FLAC/assert.h"
39 #include "share/alloc.h"
40
41 void *FLAC__memory_alloc_aligned(size_t bytes, void **aligned_address)
42 {
43         void *x;
44
45         FLAC__ASSERT(0 != aligned_address);
46
47 #ifdef FLAC__ALIGN_MALLOC_DATA
48         /* align on 32-byte (256-bit) boundary */
49         x = safe_malloc_add_2op_(bytes, /*+*/31);
50 #ifdef SIZEOF_VOIDP
51 #if SIZEOF_VOIDP == 4
52                 /* could do  *aligned_address = x + ((unsigned) (32 - (((unsigned)x) & 31))) & 31; */
53                 *aligned_address = (void*)(((unsigned)x + 31) & -32);
54 #elif SIZEOF_VOIDP == 8
55                 *aligned_address = (void*)(((FLAC__uint64)x + 31) & (FLAC__uint64)(-((FLAC__int64)32)));
56 #else
57 # error  Unsupported sizeof(void*)
58 #endif
59 #else
60         /* there's got to be a better way to do this right for all archs */
61         if(sizeof(void*) == sizeof(unsigned))
62                 *aligned_address = (void*)(((unsigned)x + 31) & -32);
63         else if(sizeof(void*) == sizeof(FLAC__uint64))
64                 *aligned_address = (void*)(((FLAC__uint64)x + 31) & (FLAC__uint64)(-((FLAC__int64)32)));
65         else
66                 return 0;
67 #endif
68 #else
69         x = safe_malloc_(bytes);
70         *aligned_address = x;
71 #endif
72         return x;
73 }
74
75 FLAC__bool FLAC__memory_alloc_aligned_int32_array(size_t elements, FLAC__int32 **unaligned_pointer, FLAC__int32 **aligned_pointer)
76 {
77         FLAC__int32 *pu; /* unaligned pointer */
78         union { /* union needed to comply with C99 pointer aliasing rules */
79                 FLAC__int32 *pa; /* aligned pointer */
80                 void        *pv; /* aligned pointer alias */
81         } u;
82
83         FLAC__ASSERT(elements > 0);
84         FLAC__ASSERT(0 != unaligned_pointer);
85         FLAC__ASSERT(0 != aligned_pointer);
86         FLAC__ASSERT(unaligned_pointer != aligned_pointer);
87
88         if(elements > SIZE_MAX / sizeof(*pu)) /* overflow check */
89                 return false;
90
91         pu = FLAC__memory_alloc_aligned(sizeof(*pu) * elements, &u.pv);
92         if(0 == pu) {
93                 return false;
94         }
95         else {
96                 if(*unaligned_pointer != 0)
97                         free(*unaligned_pointer);
98                 *unaligned_pointer = pu;
99                 *aligned_pointer = u.pa;
100                 return true;
101         }
102 }
103
104 FLAC__bool FLAC__memory_alloc_aligned_uint32_array(size_t elements, FLAC__uint32 **unaligned_pointer, FLAC__uint32 **aligned_pointer)
105 {
106         FLAC__uint32 *pu; /* unaligned pointer */
107         union { /* union needed to comply with C99 pointer aliasing rules */
108                 FLAC__uint32 *pa; /* aligned pointer */
109                 void         *pv; /* aligned pointer alias */
110         } u;
111
112         FLAC__ASSERT(elements > 0);
113         FLAC__ASSERT(0 != unaligned_pointer);
114         FLAC__ASSERT(0 != aligned_pointer);
115         FLAC__ASSERT(unaligned_pointer != aligned_pointer);
116
117         if(elements > SIZE_MAX / sizeof(*pu)) /* overflow check */
118                 return false;
119
120         pu = FLAC__memory_alloc_aligned(sizeof(*pu) * elements, &u.pv);
121         if(0 == pu) {
122                 return false;
123         }
124         else {
125                 if(*unaligned_pointer != 0)
126                         free(*unaligned_pointer);
127                 *unaligned_pointer = pu;
128                 *aligned_pointer = u.pa;
129                 return true;
130         }
131 }
132
133 FLAC__bool FLAC__memory_alloc_aligned_uint64_array(size_t elements, FLAC__uint64 **unaligned_pointer, FLAC__uint64 **aligned_pointer)
134 {
135         FLAC__uint64 *pu; /* unaligned pointer */
136         union { /* union needed to comply with C99 pointer aliasing rules */
137                 FLAC__uint64 *pa; /* aligned pointer */
138                 void         *pv; /* aligned pointer alias */
139         } u;
140
141         FLAC__ASSERT(elements > 0);
142         FLAC__ASSERT(0 != unaligned_pointer);
143         FLAC__ASSERT(0 != aligned_pointer);
144         FLAC__ASSERT(unaligned_pointer != aligned_pointer);
145
146         if(elements > SIZE_MAX / sizeof(*pu)) /* overflow check */
147                 return false;
148
149         pu = FLAC__memory_alloc_aligned(sizeof(*pu) * elements, &u.pv);
150         if(0 == pu) {
151                 return false;
152         }
153         else {
154                 if(*unaligned_pointer != 0)
155                         free(*unaligned_pointer);
156                 *unaligned_pointer = pu;
157                 *aligned_pointer = u.pa;
158                 return true;
159         }
160 }
161
162 FLAC__bool FLAC__memory_alloc_aligned_unsigned_array(size_t elements, unsigned **unaligned_pointer, unsigned **aligned_pointer)
163 {
164         unsigned *pu; /* unaligned pointer */
165         union { /* union needed to comply with C99 pointer aliasing rules */
166                 unsigned *pa; /* aligned pointer */
167                 void     *pv; /* aligned pointer alias */
168         } u;
169
170         FLAC__ASSERT(elements > 0);
171         FLAC__ASSERT(0 != unaligned_pointer);
172         FLAC__ASSERT(0 != aligned_pointer);
173         FLAC__ASSERT(unaligned_pointer != aligned_pointer);
174
175         if(elements > SIZE_MAX / sizeof(*pu)) /* overflow check */
176                 return false;
177
178         pu = FLAC__memory_alloc_aligned(sizeof(*pu) * elements, &u.pv);
179         if(0 == pu) {
180                 return false;
181         }
182         else {
183                 if(*unaligned_pointer != 0)
184                         free(*unaligned_pointer);
185                 *unaligned_pointer = pu;
186                 *aligned_pointer = u.pa;
187                 return true;
188         }
189 }
190
191 #ifndef FLAC__INTEGER_ONLY_LIBRARY
192
193 FLAC__bool FLAC__memory_alloc_aligned_real_array(size_t elements, FLAC__real **unaligned_pointer, FLAC__real **aligned_pointer)
194 {
195         FLAC__real *pu; /* unaligned pointer */
196         union { /* union needed to comply with C99 pointer aliasing rules */
197                 FLAC__real *pa; /* aligned pointer */
198                 void       *pv; /* aligned pointer alias */
199         } u;
200
201         FLAC__ASSERT(elements > 0);
202         FLAC__ASSERT(0 != unaligned_pointer);
203         FLAC__ASSERT(0 != aligned_pointer);
204         FLAC__ASSERT(unaligned_pointer != aligned_pointer);
205
206         if(elements > SIZE_MAX / sizeof(*pu)) /* overflow check */
207                 return false;
208
209         pu = FLAC__memory_alloc_aligned(sizeof(*pu) * elements, &u.pv);
210         if(0 == pu) {
211                 return false;
212         }
213         else {
214                 if(*unaligned_pointer != 0)
215                         free(*unaligned_pointer);
216                 *unaligned_pointer = pu;
217                 *aligned_pointer = u.pa;
218                 return true;
219         }
220 }
221
222 #endif
223
224 void *safe_malloc_mul_2op_p(size_t size1, size_t size2)
225 {
226         if(!size1 || !size2)
227                 return malloc(1); /* malloc(0) is undefined; FLAC src convention is to always allocate */
228         if(size1 > SIZE_MAX / size2)
229                 return 0;
230         return malloc(size1*size2);
231 }