1 /*
2 * Copyright 2013 MongoDB, Inc.
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17
18 #include <stdlib.h>
19 #include <string.h>
20
21 #include "bson-atomic.h"
22 #include "bson-config.h"
23 #include "bson-memory.h"
24
25
26 static bson_mem_vtable_t gMemVtable = {
27 malloc,
28 calloc,
29 #ifdef BSON_HAVE_REALLOCF
30 reallocf,
31 #else
32 realloc,
33 #endif
34 free,
35 };
36
37
38 /*
39 *--------------------------------------------------------------------------
40 *
41 * bson_malloc --
42 *
43 * Allocates @num_bytes of memory and returns a pointer to it. If
44 * malloc failed to allocate the memory, abort() is called.
45 *
46 * Libbson does not try to handle OOM conditions as it is beyond the
47 * scope of this library to handle so appropriately.
48 *
49 * Parameters:
50 * @num_bytes: The number of bytes to allocate.
51 *
52 * Returns:
53 * A pointer if successful; otherwise abort() is called and this
54 * function will never return.
55 *
56 * Side effects:
57 * None.
58 *
59 *--------------------------------------------------------------------------
60 */
61
62 void *
bson_malloc(size_t num_bytes)63 bson_malloc (size_t num_bytes) /* IN */
64 {
65 void *mem = NULL;
66
67 if (BSON_LIKELY (num_bytes)) {
68 if (BSON_UNLIKELY (!(mem = gMemVtable.malloc (num_bytes)))) {
69 abort ();
70 }
71 }
72
73 return mem;
74 }
75
76
77 /*
78 *--------------------------------------------------------------------------
79 *
80 * bson_malloc0 --
81 *
82 * Like bson_malloc() except the memory is zeroed first. This is
83 * similar to calloc() except that abort() is called in case of
84 * failure to allocate memory.
85 *
86 * Parameters:
87 * @num_bytes: The number of bytes to allocate.
88 *
89 * Returns:
90 * A pointer if successful; otherwise abort() is called and this
91 * function will never return.
92 *
93 * Side effects:
94 * None.
95 *
96 *--------------------------------------------------------------------------
97 */
98
99 void *
bson_malloc0(size_t num_bytes)100 bson_malloc0 (size_t num_bytes) /* IN */
101 {
102 void *mem = NULL;
103
104 if (BSON_LIKELY (num_bytes)) {
105 if (BSON_UNLIKELY (!(mem = gMemVtable.calloc (1, num_bytes)))) {
106 abort ();
107 }
108 }
109
110 return mem;
111 }
112
113
114 /*
115 *--------------------------------------------------------------------------
116 *
117 * bson_realloc --
118 *
119 * This function behaves similar to realloc() except that if there is
120 * a failure abort() is called.
121 *
122 * Parameters:
123 * @mem: The memory to realloc, or NULL.
124 * @num_bytes: The size of the new allocation or 0 to free.
125 *
126 * Returns:
127 * The new allocation if successful; otherwise abort() is called and
128 * this function never returns.
129 *
130 * Side effects:
131 * None.
132 *
133 *--------------------------------------------------------------------------
134 */
135
136 void *
bson_realloc(void * mem,size_t num_bytes)137 bson_realloc (void *mem, /* IN */
138 size_t num_bytes) /* IN */
139 {
140 /*
141 * Not all platforms are guaranteed to free() the memory if a call to
142 * realloc() with a size of zero occurs. Windows, Linux, and FreeBSD do,
143 * however, OS X does not.
144 */
145 if (BSON_UNLIKELY (num_bytes == 0)) {
146 gMemVtable.free (mem);
147 return NULL;
148 }
149
150 mem = gMemVtable.realloc (mem, num_bytes);
151
152 if (BSON_UNLIKELY (!mem)) {
153 abort ();
154 }
155
156 return mem;
157 }
158
159
160 /*
161 *--------------------------------------------------------------------------
162 *
163 * bson_realloc_ctx --
164 *
165 * This wraps bson_realloc and provides a compatible api for similar
166 * functions with a context
167 *
168 * Parameters:
169 * @mem: The memory to realloc, or NULL.
170 * @num_bytes: The size of the new allocation or 0 to free.
171 * @ctx: Ignored
172 *
173 * Returns:
174 * The new allocation if successful; otherwise abort() is called and
175 * this function never returns.
176 *
177 * Side effects:
178 * None.
179 *
180 *--------------------------------------------------------------------------
181 */
182
183
184 void *
bson_realloc_ctx(void * mem,size_t num_bytes,void * ctx)185 bson_realloc_ctx (void *mem, /* IN */
186 size_t num_bytes, /* IN */
187 void *ctx) /* IN */
188 {
189 return bson_realloc (mem, num_bytes);
190 }
191
192
193 /*
194 *--------------------------------------------------------------------------
195 *
196 * bson_free --
197 *
198 * Frees @mem using the underlying allocator.
199 *
200 * Currently, this only calls free() directly, but that is subject to
201 * change.
202 *
203 * Parameters:
204 * @mem: An allocation to free.
205 *
206 * Returns:
207 * None.
208 *
209 * Side effects:
210 * None.
211 *
212 *--------------------------------------------------------------------------
213 */
214
215 void
bson_free(void * mem)216 bson_free (void *mem) /* IN */
217 {
218 gMemVtable.free (mem);
219 }
220
221
222 /*
223 *--------------------------------------------------------------------------
224 *
225 * bson_zero_free --
226 *
227 * Frees @mem using the underlying allocator. @size bytes of @mem will
228 * be zeroed before freeing the memory. This is useful in scenarios
229 * where @mem contains passwords or other sensitive information.
230 *
231 * Parameters:
232 * @mem: An allocation to free.
233 * @size: The number of bytes in @mem.
234 *
235 * Returns:
236 * None.
237 *
238 * Side effects:
239 * None.
240 *
241 *--------------------------------------------------------------------------
242 */
243
244 void
bson_zero_free(void * mem,size_t size)245 bson_zero_free (void *mem, /* IN */
246 size_t size) /* IN */
247 {
248 if (BSON_LIKELY (mem)) {
249 memset (mem, 0, size);
250 gMemVtable.free (mem);
251 }
252 }
253
254
255 /*
256 *--------------------------------------------------------------------------
257 *
258 * bson_mem_set_vtable --
259 *
260 * This function will change our allocationt vtable.
261 *
262 * It is imperitive that this is called at the beginning of the
263 * process before any memory has been allocated by the default
264 * allocator.
265 *
266 * Returns:
267 * None.
268 *
269 * Side effects:
270 * None.
271 *
272 *--------------------------------------------------------------------------
273 */
274
275 void
bson_mem_set_vtable(const bson_mem_vtable_t * vtable)276 bson_mem_set_vtable (const bson_mem_vtable_t *vtable)
277 {
278 BSON_ASSERT (vtable);
279
280 if (!vtable->malloc || !vtable->calloc || !vtable->realloc ||
281 !vtable->free) {
282 fprintf (stderr,
283 "Failure to install BSON vtable, "
284 "missing functions.\n");
285 return;
286 }
287
288 gMemVtable = *vtable;
289 }
290
291 void
bson_mem_restore_vtable(void)292 bson_mem_restore_vtable (void)
293 {
294 bson_mem_vtable_t vtable = {
295 malloc,
296 calloc,
297 #ifdef BSON_HAVE_REALLOCF
298 reallocf,
299 #else
300 realloc,
301 #endif
302 free,
303 };
304
305 bson_mem_set_vtable (&vtable);
306 }
307