Skip to content

Commit ba380a3

Browse files
author
mdbmes
authored
CDRIVER-5914: fix for internal issue (#1894)
1 parent 57bffac commit ba380a3

File tree

2 files changed

+91
-23
lines changed

2 files changed

+91
-23
lines changed

src/libbson/src/bson/bson.c

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2015,6 +2015,10 @@ bson_new_from_buffer (uint8_t **buf, size_t *buf_len, bson_realloc_func realloc_
20152015

20162016
memcpy (&len_le, *buf, sizeof (len_le));
20172017
length = BSON_UINT32_FROM_LE (len_le);
2018+
if ((size_t) length > *buf_len) {
2019+
bson_free (bson);
2020+
return NULL;
2021+
}
20182022
}
20192023

20202024
if ((*buf)[length - 1]) {

src/libbson/tests/test-bson.c

Lines changed: 87 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -1264,45 +1264,109 @@ test_bson_init_static (void)
12641264
bson_destroy (&b);
12651265
}
12661266

1267+
static void *
1268+
realloc_func_never_called (void *mem, size_t num_bytes, void *ctx)
1269+
{
1270+
// Reallocate function for tests that should never reallocate
1271+
BSON_UNUSED (num_bytes);
1272+
BSON_UNUSED (ctx);
1273+
BSON_ASSERT (false);
1274+
return mem;
1275+
}
12671276

12681277
static void
12691278
test_bson_new_from_buffer (void)
12701279
{
1271-
bson_t *b;
1272-
uint8_t *buf = bson_malloc0 (5);
1273-
size_t len = 5;
1274-
uint32_t len_le = BSON_UINT32_TO_LE (5);
1280+
// Buffer size matches document size
1281+
{
1282+
uint8_t *buf = bson_malloc0 (5);
1283+
size_t len = 5;
1284+
uint32_t len_le = BSON_UINT32_TO_LE (5);
12751285

1276-
memcpy (buf, &len_le, sizeof (len_le));
1286+
memcpy (buf, &len_le, sizeof (len_le));
12771287

1278-
b = bson_new_from_buffer (&buf, &len, bson_realloc_ctx, NULL);
1288+
bson_t *b = bson_new_from_buffer (&buf, &len, bson_realloc_ctx, NULL);
12791289

1280-
BSON_ASSERT (b->flags & BSON_FLAG_NO_FREE);
1281-
BSON_ASSERT (len == 5);
1282-
BSON_ASSERT (b->len == 5);
1290+
BSON_ASSERT (b->flags & BSON_FLAG_NO_FREE);
1291+
BSON_ASSERT (len == 5);
1292+
BSON_ASSERT (b->len == 5);
12831293

1284-
bson_append_utf8 (b, "hello", -1, "world", -1);
1294+
bson_append_utf8 (b, "hello", -1, "world", -1);
12851295

1286-
BSON_ASSERT (len == 32);
1287-
BSON_ASSERT (b->len == 22);
1296+
BSON_ASSERT (len == 32);
1297+
BSON_ASSERT (b->len == 22);
12881298

1289-
bson_destroy (b);
1299+
bson_destroy (b);
1300+
BSON_ASSERT (buf);
1301+
bson_free (buf);
1302+
}
12901303

1291-
bson_free (buf);
1304+
// Buffer is NULL. An empty document will be allocated.
1305+
{
1306+
uint8_t *buf = NULL;
1307+
size_t len = 0;
12921308

1293-
buf = NULL;
1294-
len = 0;
1309+
bson_t *b = bson_new_from_buffer (&buf, &len, bson_realloc_ctx, NULL);
12951310

1296-
b = bson_new_from_buffer (&buf, &len, bson_realloc_ctx, NULL);
1311+
BSON_ASSERT (b->flags & BSON_FLAG_NO_FREE);
1312+
BSON_ASSERT (len == 5);
1313+
BSON_ASSERT (b->len == 5);
12971314

1298-
BSON_ASSERT (b->flags & BSON_FLAG_NO_FREE);
1299-
BSON_ASSERT (len == 5);
1300-
BSON_ASSERT (b->len == 5);
1315+
bson_destroy (b);
1316+
BSON_ASSERT (buf);
1317+
bson_free (buf);
1318+
}
13011319

1302-
bson_destroy (b);
1303-
bson_free (buf);
1304-
}
1320+
// Buffer is larger than the document. Expect it to be growable without reallocating.
1321+
{
1322+
size_t buf_len = 0x10000;
1323+
uint8_t *buf = bson_malloc0 (buf_len);
1324+
uint32_t doc_len_le = BSON_UINT32_TO_LE (5);
1325+
1326+
memcpy (buf, &doc_len_le, sizeof (doc_len_le));
1327+
1328+
bson_t *b = bson_new_from_buffer (&buf, &buf_len, realloc_func_never_called, NULL);
1329+
1330+
BSON_ASSERT (b->flags & BSON_FLAG_NO_FREE);
1331+
BSON_ASSERT (buf_len == 0x10000);
1332+
BSON_ASSERT (&buf_len == ((bson_impl_alloc_t *) b)->buflen);
1333+
BSON_ASSERT (b->len == 5);
1334+
1335+
bson_append_utf8 (b, "hello", -1, "world", -1);
13051336

1337+
BSON_ASSERT (buf_len == 0x10000);
1338+
BSON_ASSERT (b->len == 22);
1339+
1340+
bson_destroy (b);
1341+
BSON_ASSERT (buf);
1342+
bson_free (buf);
1343+
}
1344+
1345+
// Otherwise valid, but buffer is smaller than the document size. bson_new_from_buffer() must fail.
1346+
{
1347+
uint8_t *buf = NULL;
1348+
size_t buf_len = SIZE_MAX; // Must be ignored when buf == NULL
1349+
1350+
// Start with a valid doc
1351+
bson_t *valid_doc = bson_new_from_buffer (&buf, &buf_len, bson_realloc_ctx, NULL);
1352+
BSON_ASSERT (BSON_APPEND_UTF8 (valid_doc, "hello", "world"));
1353+
ASSERT_CMPUINT32 (valid_doc->len, ==, 22);
1354+
bson_destroy (valid_doc);
1355+
ASSERT_CMPSIZE_T (buf_len, ==, 32);
1356+
1357+
// Check that a slightly-too-small buffer is rejected
1358+
buf_len = 21;
1359+
BSON_ASSERT (!bson_new_from_buffer (&buf, &buf_len, realloc_func_never_called, NULL));
1360+
1361+
// Successful return if one more byte is included in the buf_len.
1362+
buf_len++;
1363+
bson_t *minimal = bson_new_from_buffer (&buf, &buf_len, realloc_func_never_called, NULL);
1364+
BSON_ASSERT (minimal != NULL);
1365+
ASSERT_CMPUINT32 (minimal->len, ==, 22);
1366+
bson_destroy (minimal);
1367+
bson_free (buf);
1368+
}
1369+
}
13061370

13071371
static void
13081372
test_bson_utf8_key (void)

0 commit comments

Comments
 (0)