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