Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
36 changes: 18 additions & 18 deletions src/common/src/common-bson-dsl-private.h
Original file line number Diff line number Diff line change
Expand Up @@ -659,24 +659,24 @@ BSON_IF_GNU_LIKE(_Pragma("GCC diagnostic ignored \"-Wshadow\""))
} \
} while (0);

#define _bsonParseMarkVisited(Index) \
if (1) { \
const size_t nth_int = Index / 64u; \
const size_t nth_bit = Index % 64u; \
while (nth_int >= _bpNumVisitBitInts) { \
/* Say that five times, fast: */ \
size_t new_num_visit_bit_ints = _bpNumVisitBitInts * 2u; \
uint64_t *new_visit_bit_ints = bson_malloc0(sizeof(uint64_t) * new_num_visit_bit_ints); \
memcpy(new_visit_bit_ints, _bpVisitBits, sizeof(uint64_t) * _bpNumVisitBitInts); \
if (_bpVisitBits != _bpVisitBits_static) { \
bson_free(_bpVisitBits); \
} \
_bpVisitBits = new_visit_bit_ints; \
_bpNumVisitBitInts = new_num_visit_bit_ints; \
} \
\
_bpVisitBits[nth_int] |= (UINT64_C(1) << nth_bit); \
} else \
#define _bsonParseMarkVisited(Index) \
if (1) { \
const size_t nth_int = Index / 64u; \
const size_t nth_bit = Index % 64u; \
while (nth_int >= _bpNumVisitBitInts) { \
/* Say that five times, fast: */ \
size_t new_num_visit_bit_ints = _bpNumVisitBitInts * 2u; \
uint64_t *new_visit_bit_ints = BSON_ARRAY_ALLOC0(new_num_visit_bit_ints, uint64_t); \
memcpy(new_visit_bit_ints, _bpVisitBits, sizeof(uint64_t) * _bpNumVisitBitInts); \
if (_bpVisitBits != _bpVisitBits_static) { \
bson_free(_bpVisitBits); \
} \
_bpVisitBits = new_visit_bit_ints; \
_bpNumVisitBitInts = new_num_visit_bit_ints; \
} \
\
_bpVisitBits[nth_int] |= (UINT64_C(1) << nth_bit); \
} else \
((void)0)

#define _bsonParseDidVisitNth(Index) _bsonParseDidVisitNth_1(Index / 64u, Index % 64u)
Expand Down
2 changes: 0 additions & 2 deletions src/libbson/doc/bson_aligned_alloc.rst
Original file line number Diff line number Diff line change
Expand Up @@ -22,8 +22,6 @@ Description

This is a portable ``aligned_alloc()`` wrapper.

In general, this function will return an allocation at least ``sizeof(void*)`` bytes or bigger with an alignment of at least ``alignment``.

If there was a failure to allocate ``num_bytes`` bytes aligned to ``alignment``, the process will be aborted.

.. warning::
Expand Down
2 changes: 0 additions & 2 deletions src/libbson/doc/bson_aligned_alloc0.rst
Original file line number Diff line number Diff line change
Expand Up @@ -22,8 +22,6 @@ Description

This is a portable ``aligned_alloc()`` wrapper that also sets the memory to zero.

In general, this function will return an allocation at least ``sizeof(void*)`` bytes or bigger with an alignment of at least ``alignment``.

If there was a failure to allocate ``num_bytes`` bytes aligned to ``alignment``, the process will be aborted.

.. warning::
Expand Down
37 changes: 37 additions & 0 deletions src/libbson/doc/bson_array_alloc.rst
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
:man_page: bson_array_alloc

bson_array_alloc()
==================

Synopsis
--------

.. code-block:: c

#define BSON_ARRAY_ALLOC(Count, Type) \
(Type*) bson_array_alloc (Count, sizeof (Type))

void *
bson_array_alloc (size_t num_elems, size_t elem_size);

Parameters
----------

* ``num_elems``: A size_t containing the number of objects to allocate.
* ``elem_size``: A size_t containing the size of each object in bytes.

Description
-----------

This is a portable ``malloc()`` wrapper to allocate an array of objects.

If ``num_elems * elem_size`` cannot be represented in a size_t or there was a failure to allocate ``num_elems * elem_size`` bytes, the process will be aborted.

.. warning::

This function will abort on failure to allocate memory.

Returns
-------

A pointer to a memory region which *HAS NOT* been zeroed.
37 changes: 37 additions & 0 deletions src/libbson/doc/bson_array_alloc0.rst
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
:man_page: bson_array_alloc0

bson_array_alloc0()
===================

Synopsis
--------

.. code-block:: c

#define BSON_ARRAY_ALLOC0(Count, Type) \
(Type*) bson_array_alloc0 (Count, sizeof (Type))

void *
bson_array_alloc0 (size_t num_elems, size_t elem_size);

Parameters
----------

* ``num_elems``: A size_t containing the number of objects to allocate.
* ``elem_size``: A size_t containing the size of each object in bytes.

Description
-----------

This is a portable ``calloc()`` wrapper to allocate an array of objects that also sets the memory to zero.

If ``num_elems * elem_size`` cannot be represented in a size_t or there was a failure to allocate ``num_elems * elem_size`` bytes, the process will be aborted.

.. warning::

This function will abort on failure to allocate memory.

Returns
-------

A pointer to a memory region which *HAS* been zeroed.
2 changes: 0 additions & 2 deletions src/libbson/doc/bson_malloc.rst
Original file line number Diff line number Diff line change
Expand Up @@ -21,8 +21,6 @@ Description

This is a portable ``malloc()`` wrapper.

In general, this function will return an allocation at least ``sizeof(void*)`` bytes or bigger.

If there was a failure to allocate ``num_bytes`` bytes, the process will be aborted.

.. warning::
Expand Down
2 changes: 0 additions & 2 deletions src/libbson/doc/bson_malloc0.rst
Original file line number Diff line number Diff line change
Expand Up @@ -21,8 +21,6 @@ Description

This is a portable ``malloc()`` wrapper that also sets the memory to zero. Similar to ``calloc()``.

In general, this function will return an allocation at least ``sizeof(void*)`` bytes or bigger.

If there was a failure to allocate ``num_bytes`` bytes, the process will be aborted.

.. warning::
Expand Down
2 changes: 2 additions & 0 deletions src/libbson/doc/bson_memory.rst
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,8 @@ To aid in language binding integration, Libbson allows for setting a custom memo
bson_malloc0
bson_aligned_alloc
bson_aligned_alloc0
bson_array_alloc
bson_array_alloc0
bson_mem_restore_vtable
bson_mem_set_vtable
bson_realloc
Expand Down
2 changes: 1 addition & 1 deletion src/libbson/doc/bson_realloc.rst
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ Description

This is a portable ``realloc()`` wrapper.

In general, this function will return an allocation at least ``sizeof(void*)`` bytes or bigger. If ``num_bytes`` is 0, then the allocation will be freed.
If ``num_bytes`` is 0, then the allocation will be freed.

If there was a failure to allocate ``num_bytes`` bytes, the process will be aborted.

Expand Down
74 changes: 74 additions & 0 deletions src/libbson/src/bson/memory.c
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@

#include <bson/config.h>

#include <mlib/ckdint.h>
#include <mlib/config.h>

#include <errno.h>
Expand Down Expand Up @@ -231,6 +232,79 @@ bson_aligned_alloc0(size_t alignment /* IN */, size_t num_bytes /* IN */)
}


/*
*--------------------------------------------------------------------------
*
* bson_array_alloc --
*
* Allocates memory for an array of objects.
*
* Libbson does not try to handle OOM conditions as it is beyond the
* scope of this library to handle so appropriately.
*
* Parameters:
* @num_elems: The number of objects to allocate.
* @elem_size: The size of each object in bytes.
*
* Returns:
* A pointer if successful; otherwise abort() is called and this
* function will never return.
*
*--------------------------------------------------------------------------
*/

void *
bson_array_alloc(size_t num_elems /* IN */, size_t elem_size /* IN */)
{
void *mem = NULL;
size_t num_bytes = 0;
BSON_ASSERT(!mlib_mul(&num_bytes, num_elems, elem_size));

if (BSON_LIKELY(num_bytes)) {
mem = bson_malloc(num_bytes);
}
return mem;
}

/*
*--------------------------------------------------------------------------
*
* bson_array_alloc0--
*
* Like bson_array_alloc() except the memory is zeroed after allocation
* for convenience.
*
* Parameters:
* @num_elems: The number of objects to allocate.
* @elem_size: The size of each object in bytes.
*
* Returns:
* A pointer if successful; otherwise abort() is called and this
* function will never return.
*
* Side effects:
* None.
*
*--------------------------------------------------------------------------
*/

void *
bson_array_alloc0(size_t num_elems /* IN */, size_t elem_size /* IN */)
{
void *mem = NULL;
size_t num_bytes = 0;
BSON_ASSERT(!mlib_mul(&num_bytes, num_elems, elem_size));

if (BSON_LIKELY(num_bytes)) {
if (BSON_UNLIKELY(!(mem = gMemVtable.calloc(num_elems, elem_size)))) {
fprintf(stderr, "Failure to allocate memory in bson_array_alloc0(). errno: %d.\n", errno);
abort();
}
}
return mem;
}


/*
*--------------------------------------------------------------------------
*
Expand Down
6 changes: 6 additions & 0 deletions src/libbson/src/bson/memory.h
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,10 @@ bson_aligned_alloc(size_t alignment, size_t num_bytes);
BSON_EXPORT(void *)
bson_aligned_alloc0(size_t alignment, size_t num_bytes);
BSON_EXPORT(void *)
bson_array_alloc(size_t num_elems, size_t elem_size);
BSON_EXPORT(void *)
bson_array_alloc0(size_t num_elems, size_t elem_size);
BSON_EXPORT(void *)
bson_realloc(void *mem, size_t num_bytes);
BSON_EXPORT(void *)
bson_realloc_ctx(void *mem, size_t num_bytes, void *ctx);
Expand All @@ -59,6 +63,8 @@ bson_zero_free(void *mem, size_t size);

#define BSON_ALIGNED_ALLOC(T) ((T *)(bson_aligned_alloc(BSON_ALIGNOF(T), sizeof(T))))
#define BSON_ALIGNED_ALLOC0(T) ((T *)(bson_aligned_alloc0(BSON_ALIGNOF(T), sizeof(T))))
#define BSON_ARRAY_ALLOC(N, T) ((T *)(bson_array_alloc(N, sizeof(T))))
#define BSON_ARRAY_ALLOC0(N, T) ((T *)(bson_array_alloc0(N, sizeof(T))))

BSON_END_DECLS

Expand Down
4 changes: 2 additions & 2 deletions src/libbson/src/jsonsl/jsonsl.c
Original file line number Diff line number Diff line change
Expand Up @@ -1052,9 +1052,9 @@ void jsonsl_jpr_match_state_init(jsonsl_t jsn,
if (njprs == 0) {
return;
}
jsn->jprs = (jsonsl_jpr_t *) bson_malloc (sizeof (jsonsl_jpr_t) * njprs);
jsn->jprs = BSON_ARRAY_ALLOC(njprs, jsonsl_jpr_t);
jsn->jpr_count = njprs;
jsn->jpr_root = (size_t *) bson_malloc0 (sizeof (size_t) * njprs * jsn->levels_max);
jsn->jpr_root = BSON_ARRAY_ALLOC0(njprs * jsn->levels_max, size_t);
memcpy(jsn->jprs, jprs, sizeof(jsonsl_jpr_t) * njprs);
/* Set the initial jump table values */

Expand Down
18 changes: 9 additions & 9 deletions src/libbson/tests/test-bson-vector.c
Original file line number Diff line number Diff line change
Expand Up @@ -920,8 +920,8 @@ test_bson_vector_view_api_fuzz_int8(void)
{
size_t current_length = 0;
bson_t vector_doc = BSON_INITIALIZER;
int8_t *expected_elements = bson_malloc(MAX_TESTED_VECTOR_LENGTH * sizeof *expected_elements);
int8_t *actual_elements = bson_malloc(MAX_TESTED_VECTOR_LENGTH * sizeof *actual_elements);
int8_t *expected_elements = BSON_ARRAY_ALLOC(MAX_TESTED_VECTOR_LENGTH, int8_t);
int8_t *actual_elements = BSON_ARRAY_ALLOC(MAX_TESTED_VECTOR_LENGTH, int8_t);
for (int fuzz_iter = 0; fuzz_iter < FUZZ_TEST_ITERS; fuzz_iter++) {
unsigned r = (unsigned)rand();
unsigned r_operation = r & 0xFu;
Expand Down Expand Up @@ -974,8 +974,8 @@ test_bson_vector_view_api_fuzz_float32(void)
{
size_t current_length = 0;
bson_t vector_doc = BSON_INITIALIZER;
float *expected_elements = bson_malloc(MAX_TESTED_VECTOR_LENGTH * sizeof *expected_elements);
float *actual_elements = bson_malloc(MAX_TESTED_VECTOR_LENGTH * sizeof *actual_elements);
float *expected_elements = BSON_ARRAY_ALLOC(MAX_TESTED_VECTOR_LENGTH, float);
float *actual_elements = BSON_ARRAY_ALLOC(MAX_TESTED_VECTOR_LENGTH, float);
for (int fuzz_iter = 0; fuzz_iter < FUZZ_TEST_ITERS; fuzz_iter++) {
unsigned r = (unsigned)rand();
unsigned r_operation = r & 0xFu;
Expand Down Expand Up @@ -1028,8 +1028,8 @@ test_bson_vector_view_api_fuzz_packed_bit(void)
{
size_t current_length = 0;
bson_t vector_doc = BSON_INITIALIZER;
bool *expected_elements = bson_malloc(MAX_TESTED_VECTOR_LENGTH * sizeof *expected_elements);
bool *actual_elements = bson_malloc(MAX_TESTED_VECTOR_LENGTH * sizeof *actual_elements);
bool *expected_elements = BSON_ARRAY_ALLOC(MAX_TESTED_VECTOR_LENGTH, bool);
bool *actual_elements = BSON_ARRAY_ALLOC(MAX_TESTED_VECTOR_LENGTH, bool);
uint8_t *packed_buffer = bson_malloc((MAX_TESTED_VECTOR_LENGTH + 7) / 8);
for (int fuzz_iter = 0; fuzz_iter < FUZZ_TEST_ITERS; fuzz_iter++) {
unsigned r = (unsigned)rand();
Expand Down Expand Up @@ -1392,7 +1392,7 @@ test_bson_vector_edge_cases_int8(void)
// Test some read and write boundaries.
{
size_t values_size = 100;
int8_t *values = bson_malloc0(values_size * sizeof *values);
int8_t *values = BSON_ARRAY_ALLOC0(values_size, int8_t);
TEST_BSON_VECTOR_EDGE_CASES_RW_COMMON(
view, max_alloc_elements, values, values_size, bson_vector_int8_view_read, bson_vector_int8_view_write);
bson_free(values);
Expand Down Expand Up @@ -1439,7 +1439,7 @@ test_bson_vector_edge_cases_float32(void)
// Test some read and write boundaries.
{
size_t values_size = 100;
float *values = bson_malloc0(values_size * sizeof *values);
float *values = BSON_ARRAY_ALLOC0(values_size, float);
TEST_BSON_VECTOR_EDGE_CASES_RW_COMMON(
view, max_alloc_elements, values, values_size, bson_vector_float32_view_read, bson_vector_float32_view_write);
bson_free(values);
Expand Down Expand Up @@ -1506,7 +1506,7 @@ test_bson_vector_edge_cases_packed_bit(void)
// Only tests one length, but it's chosen to be greater than 8 and not a multiple of 8.
{
size_t values_size = 190;
bool *values = bson_malloc0(values_size * sizeof *values);
bool *values = BSON_ARRAY_ALLOC0(values_size, bool);
TEST_BSON_VECTOR_EDGE_CASES_RW_COMMON(view,
max_alloc_elements,
values,
Expand Down
20 changes: 20 additions & 0 deletions src/libbson/tests/test-bson.c
Original file line number Diff line number Diff line change
Expand Up @@ -124,6 +124,25 @@ test_bson_alloc(void)
}


static void
test_bson_array_alloc(void)
{
// Can allocate an array of items:
{
int *arr = BSON_ARRAY_ALLOC(2, int);
arr[0] = 1;
arr[1] = 2;
bson_free(arr);
}

// Allocating with overflow in byte size aborts:
mlib_assert_aborts () {
int *arr = BSON_ARRAY_ALLOC(SIZE_MAX, int);
bson_free(arr);
}
}


static void
BSON_ASSERT_BSON_EQUAL(const bson_t *a, const bson_t *b)
{
Expand Down Expand Up @@ -2971,6 +2990,7 @@ test_bson_install(TestSuite *suite)
TestSuite_Add(suite, "/bson/init", test_bson_init);
TestSuite_Add(suite, "/bson/init_static", test_bson_init_static);
TestSuite_Add(suite, "/bson/basic", test_bson_alloc);
TestSuite_Add(suite, "/bson/basic_array_alloc", test_bson_array_alloc);
TestSuite_Add(suite, "/bson/append_overflow", test_bson_append_overflow);
TestSuite_Add(suite, "/bson/append_array", test_bson_append_array);
TestSuite_Add(suite, "/bson/append_binary", test_bson_append_binary);
Expand Down
2 changes: 1 addition & 1 deletion src/libmongoc/src/mongoc/mcd-rpc.c
Original file line number Diff line number Diff line change
Expand Up @@ -957,7 +957,7 @@ _append_iovec_reserve_space_for(mongoc_iovec_t **iovecs,
BSON_ASSERT(*capacity == 4u);

*capacity += additional_capacity;
*iovecs = bson_malloc(*capacity * sizeof(mongoc_iovec_t));
*iovecs = BSON_ARRAY_ALLOC(*capacity, mongoc_iovec_t);
memcpy(*iovecs, header_iovecs, 4u * sizeof(mongoc_iovec_t));
}

Expand Down
Loading