1/* libFLAC - Free Lossless Audio Codec library
2 * Copyright (C) 2001-2009  Josh Coalson
3 * Copyright (C) 2011-2014  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/alloc.h"
44
45void *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
62FLAC__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__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
91FLAC__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__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
120FLAC__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__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
149FLAC__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 = 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
180FLAC__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__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
211void *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