ce188d4d |
1 | /* alloc - Convenience routines for safely allocating memory |
2 | * Copyright (C) 2007-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 | #ifndef FLAC__SHARE__ALLOC_H |
34 | #define FLAC__SHARE__ALLOC_H |
35 | |
36 | #ifdef HAVE_CONFIG_H |
37 | # include <config.h> |
38 | #endif |
39 | |
40 | /* WATCHOUT: for c++ you may have to #define __STDC_LIMIT_MACROS 1 real early |
41 | * before #including this file, otherwise SIZE_MAX might not be defined |
42 | */ |
43 | |
44 | #include <limits.h> /* for SIZE_MAX */ |
45 | #if HAVE_STDINT_H |
46 | #include <stdint.h> /* for SIZE_MAX in case limits.h didn't get it */ |
47 | #endif |
48 | #include <stdlib.h> /* for size_t, malloc(), etc */ |
49 | #include "share/compat.h" |
50 | |
51 | #ifndef SIZE_MAX |
52 | # ifndef SIZE_T_MAX |
53 | # ifdef _MSC_VER |
54 | # ifdef _WIN64 |
55 | # define SIZE_T_MAX FLAC__U64L(0xffffffffffffffff) |
56 | # else |
57 | # define SIZE_T_MAX 0xffffffff |
58 | # endif |
59 | # else |
60 | # error |
61 | # endif |
62 | # endif |
63 | # define SIZE_MAX SIZE_T_MAX |
64 | #endif |
65 | |
66 | /* avoid malloc()ing 0 bytes, see: |
67 | * https://www.securecoding.cert.org/confluence/display/seccode/MEM04-A.+Do+not+make+assumptions+about+the+result+of+allocating+0+bytes?focusedCommentId=5407003 |
68 | */ |
69 | static inline void *safe_malloc_(size_t size) |
70 | { |
71 | /* malloc(0) is undefined; FLAC src convention is to always allocate */ |
72 | if(!size) |
73 | size++; |
74 | return malloc(size); |
75 | } |
76 | |
77 | static inline void *safe_calloc_(size_t nmemb, size_t size) |
78 | { |
79 | if(!nmemb || !size) |
80 | return malloc(1); /* malloc(0) is undefined; FLAC src convention is to always allocate */ |
81 | return calloc(nmemb, size); |
82 | } |
83 | |
84 | /*@@@@ there's probably a better way to prevent overflows when allocating untrusted sums but this works for now */ |
85 | |
86 | static inline void *safe_malloc_add_2op_(size_t size1, size_t size2) |
87 | { |
88 | size2 += size1; |
89 | if(size2 < size1) |
90 | return 0; |
91 | return safe_malloc_(size2); |
92 | } |
93 | |
94 | static inline void *safe_malloc_add_3op_(size_t size1, size_t size2, size_t size3) |
95 | { |
96 | size2 += size1; |
97 | if(size2 < size1) |
98 | return 0; |
99 | size3 += size2; |
100 | if(size3 < size2) |
101 | return 0; |
102 | return safe_malloc_(size3); |
103 | } |
104 | |
105 | static inline void *safe_malloc_add_4op_(size_t size1, size_t size2, size_t size3, size_t size4) |
106 | { |
107 | size2 += size1; |
108 | if(size2 < size1) |
109 | return 0; |
110 | size3 += size2; |
111 | if(size3 < size2) |
112 | return 0; |
113 | size4 += size3; |
114 | if(size4 < size3) |
115 | return 0; |
116 | return safe_malloc_(size4); |
117 | } |
118 | |
119 | void *safe_malloc_mul_2op_(size_t size1, size_t size2) ; |
120 | |
121 | static inline void *safe_malloc_mul_3op_(size_t size1, size_t size2, size_t size3) |
122 | { |
123 | if(!size1 || !size2 || !size3) |
124 | return malloc(1); /* malloc(0) is undefined; FLAC src convention is to always allocate */ |
125 | if(size1 > SIZE_MAX / size2) |
126 | return 0; |
127 | size1 *= size2; |
128 | if(size1 > SIZE_MAX / size3) |
129 | return 0; |
130 | return malloc(size1*size3); |
131 | } |
132 | |
133 | /* size1*size2 + size3 */ |
134 | static inline void *safe_malloc_mul2add_(size_t size1, size_t size2, size_t size3) |
135 | { |
136 | if(!size1 || !size2) |
137 | return safe_malloc_(size3); |
138 | if(size1 > SIZE_MAX / size2) |
139 | return 0; |
140 | return safe_malloc_add_2op_(size1*size2, size3); |
141 | } |
142 | |
143 | /* size1 * (size2 + size3) */ |
144 | static inline void *safe_malloc_muladd2_(size_t size1, size_t size2, size_t size3) |
145 | { |
146 | if(!size1 || (!size2 && !size3)) |
147 | return malloc(1); /* malloc(0) is undefined; FLAC src convention is to always allocate */ |
148 | size2 += size3; |
149 | if(size2 < size3) |
150 | return 0; |
151 | if(size1 > SIZE_MAX / size2) |
152 | return 0; |
153 | return malloc(size1*size2); |
154 | } |
155 | |
156 | static inline void *safe_realloc_(void *ptr, size_t size) |
157 | { |
158 | void *oldptr = ptr; |
159 | void *newptr = realloc(ptr, size); |
160 | if(size > 0 && newptr == 0) |
161 | free(oldptr); |
162 | return newptr; |
163 | } |
164 | static inline void *safe_realloc_add_2op_(void *ptr, size_t size1, size_t size2) |
165 | { |
166 | size2 += size1; |
167 | if(size2 < size1) { |
168 | free(ptr); |
169 | return 0; |
170 | } |
171 | return realloc(ptr, size2); |
172 | } |
173 | |
174 | static inline void *safe_realloc_add_3op_(void *ptr, size_t size1, size_t size2, size_t size3) |
175 | { |
176 | size2 += size1; |
177 | if(size2 < size1) |
178 | return 0; |
179 | size3 += size2; |
180 | if(size3 < size2) |
181 | return 0; |
182 | return realloc(ptr, size3); |
183 | } |
184 | |
185 | static inline void *safe_realloc_add_4op_(void *ptr, size_t size1, size_t size2, size_t size3, size_t size4) |
186 | { |
187 | size2 += size1; |
188 | if(size2 < size1) |
189 | return 0; |
190 | size3 += size2; |
191 | if(size3 < size2) |
192 | return 0; |
193 | size4 += size3; |
194 | if(size4 < size3) |
195 | return 0; |
196 | return realloc(ptr, size4); |
197 | } |
198 | |
199 | static inline void *safe_realloc_mul_2op_(void *ptr, size_t size1, size_t size2) |
200 | { |
201 | if(!size1 || !size2) |
202 | return realloc(ptr, 0); /* preserve POSIX realloc(ptr, 0) semantics */ |
203 | if(size1 > SIZE_MAX / size2) |
204 | return 0; |
205 | return safe_realloc_(ptr, size1*size2); |
206 | } |
207 | |
208 | /* size1 * (size2 + size3) */ |
209 | static inline void *safe_realloc_muladd2_(void *ptr, size_t size1, size_t size2, size_t size3) |
210 | { |
211 | if(!size1 || (!size2 && !size3)) |
212 | return realloc(ptr, 0); /* preserve POSIX realloc(ptr, 0) semantics */ |
213 | size2 += size3; |
214 | if(size2 < size3) |
215 | return 0; |
216 | return safe_realloc_mul_2op_(ptr, size1, size2); |
217 | } |
218 | |
219 | #endif |