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