From Code to Community: Sponsoring The Perl and Raku Conference 2025 Learn more

/*
* Copyright 2013 MongoDB, Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#include <stdlib.h>
#include <string.h>
#include "bson-atomic.h"
#include "bson-config.h"
#include "bson-memory.h"
static bson_mem_vtable_t gMemVtable = {
malloc,
calloc,
#ifdef __APPLE__
reallocf,
#else
realloc,
#endif
free,
};
/*
*--------------------------------------------------------------------------
*
* bson_malloc --
*
* Allocates @num_bytes of memory and returns a pointer to it. If
* malloc failed to allocate the memory, abort() is called.
*
* Libbson does not try to handle OOM conditions as it is beyond the
* scope of this library to handle so appropriately.
*
* Parameters:
* @num_bytes: The number of bytes to allocate.
*
* Returns:
* A pointer if successful; otherwise abort() is called and this
* function will never return.
*
* Side effects:
* None.
*
*--------------------------------------------------------------------------
*/
void *
bson_malloc (size_t num_bytes) /* IN */
{
void *mem;
if (!(mem = gMemVtable.malloc (num_bytes))) {
abort ();
}
return mem;
}
/*
*--------------------------------------------------------------------------
*
* bson_malloc0 --
*
* Like bson_malloc() except the memory is zeroed first. This is
* similar to calloc() except that abort() is called in case of
* failure to allocate memory.
*
* Parameters:
* @num_bytes: The number of bytes to allocate.
*
* Returns:
* A pointer if successful; otherwise abort() is called and this
* function will never return.
*
* Side effects:
* None.
*
*--------------------------------------------------------------------------
*/
void *
bson_malloc0 (size_t num_bytes) /* IN */
{
void *mem = NULL;
if (BSON_LIKELY (num_bytes)) {
if (BSON_UNLIKELY (!(mem = gMemVtable.calloc (1, num_bytes)))) {
abort ();
}
}
return mem;
}
/*
*--------------------------------------------------------------------------
*
* bson_realloc --
*
* This function behaves similar to realloc() except that if there is
* a failure abort() is called.
*
* Parameters:
* @mem: The memory to realloc, or NULL.
* @num_bytes: The size of the new allocation or 0 to free.
*
* Returns:
* The new allocation if successful; otherwise abort() is called and
* this function never returns.
*
* Side effects:
* None.
*
*--------------------------------------------------------------------------
*/
void *
bson_realloc (void *mem, /* IN */
size_t num_bytes) /* IN */
{
/*
* Not all platforms are guaranteed to free() the memory if a call to
* realloc() with a size of zero occurs. Windows, Linux, and FreeBSD do,
* however, OS X does not.
*/
if (BSON_UNLIKELY (num_bytes == 0)) {
gMemVtable.free (mem);
return NULL;
}
mem = gMemVtable.realloc (mem, num_bytes);
if (BSON_UNLIKELY (!mem)) {
abort ();
}
return mem;
}
/*
*--------------------------------------------------------------------------
*
* bson_realloc_ctx --
*
* This wraps bson_realloc and provides a compatible api for similar
* functions with a context
*
* Parameters:
* @mem: The memory to realloc, or NULL.
* @num_bytes: The size of the new allocation or 0 to free.
* @ctx: Ignored
*
* Returns:
* The new allocation if successful; otherwise abort() is called and
* this function never returns.
*
* Side effects:
* None.
*
*--------------------------------------------------------------------------
*/
void *
bson_realloc_ctx (void *mem, /* IN */
size_t num_bytes, /* IN */
void *ctx) /* IN */
{
return bson_realloc (mem, num_bytes);
}
/*
*--------------------------------------------------------------------------
*
* bson_free --
*
* Frees @mem using the underlying allocator.
*
* Currently, this only calls free() directly, but that is subject to
* change.
*
* Parameters:
* @mem: An allocation to free.
*
* Returns:
* None.
*
* Side effects:
* None.
*
*--------------------------------------------------------------------------
*/
void
bson_free (void *mem) /* IN */
{
gMemVtable.free (mem);
}
/*
*--------------------------------------------------------------------------
*
* bson_zero_free --
*
* Frees @mem using the underlying allocator. @size bytes of @mem will
* be zeroed before freeing the memory. This is useful in scenarios
* where @mem contains passwords or other sensitive information.
*
* Parameters:
* @mem: An allocation to free.
* @size: The number of bytes in @mem.
*
* Returns:
* None.
*
* Side effects:
* None.
*
*--------------------------------------------------------------------------
*/
void
bson_zero_free (void *mem, /* IN */
size_t size) /* IN */
{
if (BSON_LIKELY (mem)) {
memset (mem, 0, size);
gMemVtable.free (mem);
}
}
/*
*--------------------------------------------------------------------------
*
* bson_mem_set_vtable --
*
* This function will change our allocationt vtable.
*
* It is imperitive that this is called at the beginning of the
* process before any memory has been allocated by the default
* allocator.
*
* Returns:
* None.
*
* Side effects:
* None.
*
*--------------------------------------------------------------------------
*/
void
bson_mem_set_vtable (const bson_mem_vtable_t *vtable)
{
bson_return_if_fail (vtable);
if (!vtable->malloc ||
!vtable->calloc ||
!vtable->realloc ||
!vtable->free) {
fprintf (stderr, "Failure to install BSON vtable, "
"missing functions.\n");
return;
}
gMemVtable = *vtable;
}