Skip to content

Commit 136c3db

Browse files
author
mdbmes
authored
CDRIVER-5641: Fixes for packed_bit edge cases on systems with 32-bit size_t (#1904)
1 parent be04a7e commit 136c3db

File tree

2 files changed

+29
-5
lines changed

2 files changed

+29
-5
lines changed

src/libbson/src/bson/bson-vector.h

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -296,11 +296,11 @@ bson_vector_float32_binary_data_length (size_t element_count)
296296
static BSON_INLINE uint32_t
297297
bson_vector_packed_bit_binary_data_length (size_t element_count)
298298
{
299-
const size_t max_representable = (size_t) BSON_MIN (
300-
(uint64_t) SIZE_MAX, ((uint64_t) UINT32_MAX - (uint64_t) BSON_VECTOR_HEADER_LEN) * (uint64_t) 8);
299+
const size_t max_representable =
300+
(size_t) BSON_MIN ((uint64_t) SIZE_MAX, ((uint64_t) UINT32_MAX - (uint64_t) BSON_VECTOR_HEADER_LEN) * 8u);
301301
return element_count > max_representable
302302
? 0u
303-
: (uint32_t) ((element_count + (size_t) 7) / (size_t) 8) + (uint32_t) BSON_VECTOR_HEADER_LEN;
303+
: (uint32_t) (((uint64_t) element_count + 7u) / 8u) + (uint32_t) BSON_VECTOR_HEADER_LEN;
304304
}
305305

306306

src/libbson/tests/test-bson-vector.c

Lines changed: 26 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1459,21 +1459,45 @@ test_bson_vector_edge_cases_float32 (void)
14591459
static void
14601460
test_bson_vector_edge_cases_packed_bit (void)
14611461
{
1462+
// Test UINT32_MAX as an element count. This is the largest representable on systems with a 32-bit size_t.
1463+
uint32_t len_for_max_count = (uint32_t) (((uint64_t) UINT32_MAX + 7u) / 8u + BSON_VECTOR_HEADER_LEN);
1464+
{
1465+
ASSERT_CMPUINT32 (bson_vector_packed_bit_binary_data_length ((size_t) UINT32_MAX), ==, len_for_max_count);
1466+
ASSERT_CMPUINT32 (bson_vector_packed_bit_binary_data_length ((size_t) UINT32_MAX - 1u), ==, len_for_max_count);
1467+
ASSERT_CMPUINT32 (bson_vector_packed_bit_binary_data_length ((size_t) UINT32_MAX - 6u), ==, len_for_max_count);
1468+
ASSERT_CMPUINT32 (
1469+
bson_vector_packed_bit_binary_data_length ((size_t) UINT32_MAX - 7u), ==, len_for_max_count - 1u);
1470+
ASSERT_CMPUINT32 (
1471+
bson_vector_packed_bit_binary_data_length ((size_t) UINT32_MAX - 8u), ==, len_for_max_count - 1u);
1472+
}
1473+
1474+
// Test the real max_representable_elements only if size_t is large enough.
1475+
#if SIZE_MAX > UINT32_MAX
14621476
size_t max_representable_elements = ((size_t) UINT32_MAX - BSON_VECTOR_HEADER_LEN) * 8u;
14631477

14641478
// Test binary_data_length (uint32_t) edge cases, without any allocation.
14651479
{
1480+
ASSERT_CMPUINT32 (bson_vector_packed_bit_binary_data_length ((size_t) UINT32_MAX + 1u), ==, len_for_max_count);
1481+
ASSERT_CMPUINT32 (
1482+
bson_vector_packed_bit_binary_data_length ((size_t) UINT32_MAX + 2u), ==, len_for_max_count + 1u);
1483+
ASSERT_CMPUINT32 (
1484+
bson_vector_packed_bit_binary_data_length ((size_t) UINT32_MAX + 9u), ==, len_for_max_count + 1u);
14661485
ASSERT_CMPUINT32 (
14671486
bson_vector_packed_bit_binary_data_length (max_representable_elements - 8u), ==, UINT32_MAX - 1u);
14681487
ASSERT_CMPUINT32 (bson_vector_packed_bit_binary_data_length (max_representable_elements - 7u), ==, UINT32_MAX);
14691488
ASSERT_CMPUINT32 (bson_vector_packed_bit_binary_data_length (max_representable_elements), ==, UINT32_MAX);
14701489
ASSERT_CMPUINT32 (bson_vector_packed_bit_binary_data_length (max_representable_elements + 1u), ==, 0);
14711490
}
1491+
#endif // SIZE_MAX > UINT32_MAX
14721492

1473-
// Needs little real memory because most bytes are never accessed,
1474-
// but we should require a virtual address space larger than 32 bits.
1493+
// If we additionally have a 64-bit address space, allocate this max-sized vector and run tests.
1494+
// Needs little real memory because most bytes are never accessed.
14751495
#if BSON_WORD_SIZE > 32
14761496

1497+
#if !(SIZE_MAX > UINT32_MAX)
1498+
#error 64-bit platforms should have a 64-bit size_t
1499+
#endif
1500+
14771501
size_t expected_bson_overhead =
14781502
5 /* empty bson document */ + 3 /* "v" element header */ + 5 /* binary item header */;
14791503
size_t max_alloc_bytes = (size_t) BSON_MAX_SIZE - expected_bson_overhead - BSON_VECTOR_HEADER_LEN;

0 commit comments

Comments
 (0)