Skip to content

Commit c8a2d94

Browse files
committed
Allow mongoc_buffer_t larger than INT_MAX
1 parent a09129b commit c8a2d94

File tree

2 files changed

+59
-25
lines changed

2 files changed

+59
-25
lines changed

src/libmongoc/src/mongoc/mongoc-buffer.c

Lines changed: 13 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -31,8 +31,15 @@
3131
#endif
3232

3333

34-
#define SPACE_FOR(_b, _sz) \
35-
(((ssize_t) (_b)->datalen - (ssize_t) (_b)->len) >= (ssize_t) (_sz))
34+
static inline void
35+
make_space_for (mongoc_buffer_t *buffer, size_t data_size)
36+
{
37+
if (buffer->len + data_size > buffer->datalen) {
38+
buffer->datalen = bson_next_power_of_two (buffer->len + data_size);
39+
buffer->data = (uint8_t *) buffer->realloc_func (
40+
buffer->data, buffer->datalen, buffer->realloc_data);
41+
}
42+
}
3643

3744

3845
/**
@@ -135,12 +142,7 @@ _mongoc_buffer_append (mongoc_buffer_t *buffer,
135142

136143
BSON_ASSERT (buffer->datalen);
137144

138-
if (!SPACE_FOR (buffer, data_size)) {
139-
BSON_ASSERT ((buffer->datalen + data_size) < INT_MAX);
140-
buffer->datalen = bson_next_power_of_two (data_size + buffer->len);
141-
buffer->data =
142-
(uint8_t *) buffer->realloc_func (buffer->data, buffer->datalen, NULL);
143-
}
145+
make_space_for (buffer, data_size);
144146

145147
buf = &buffer->data[buffer->len];
146148

@@ -186,12 +188,7 @@ _mongoc_buffer_append_from_stream (mongoc_buffer_t *buffer,
186188

187189
BSON_ASSERT (buffer->datalen);
188190

189-
if (!SPACE_FOR (buffer, size)) {
190-
BSON_ASSERT ((buffer->datalen + size) < INT_MAX);
191-
buffer->datalen = bson_next_power_of_two (size + buffer->len);
192-
buffer->data =
193-
(uint8_t *) buffer->realloc_func (buffer->data, buffer->datalen, NULL);
194-
}
191+
make_space_for (buffer, size);
195192

196193
buf = &buffer->data[buffer->len];
197194

@@ -260,11 +257,7 @@ _mongoc_buffer_fill (mongoc_buffer_t *buffer,
260257

261258
min_bytes -= buffer->len;
262259

263-
if (!SPACE_FOR (buffer, min_bytes)) {
264-
buffer->datalen = bson_next_power_of_two (buffer->len + min_bytes);
265-
buffer->data = (uint8_t *) buffer->realloc_func (
266-
buffer->data, buffer->datalen, buffer->realloc_data);
267-
}
260+
make_space_for (buffer, min_bytes);
268261

269262
avail_bytes = buffer->datalen - buffer->len;
270263

@@ -341,12 +334,7 @@ _mongoc_buffer_try_append_from_stream (mongoc_buffer_t *buffer,
341334

342335
BSON_ASSERT (buffer->datalen);
343336

344-
if (!SPACE_FOR (buffer, size)) {
345-
BSON_ASSERT ((buffer->datalen + size) < INT_MAX);
346-
buffer->datalen = bson_next_power_of_two (size + buffer->len);
347-
buffer->data =
348-
(uint8_t *) buffer->realloc_func (buffer->data, buffer->datalen, NULL);
349-
}
337+
make_space_for (buffer, size);
350338

351339
buf = &buffer->data[buffer->len];
352340

src/libmongoc/tests/test-mongoc-bulk.c

Lines changed: 46 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5080,6 +5080,49 @@ test_bulk_write_set_client_after_operation (void)
50805080
mongoc_client_destroy (client);
50815081
}
50825082

5083+
// Test creating a bulk write with more data than INT_MAX.
5084+
static void
5085+
test_bulk_write_more_than_INT_MAX (void)
5086+
{
5087+
bool ok;
5088+
bson_error_t error;
5089+
5090+
// Create large document.
5091+
bson_t large_doc = BSON_INITIALIZER;
5092+
{
5093+
// Maximum server document size is 16 MiB (16777216).
5094+
// Subtract 32 for overhead.
5095+
size_t large_sz = 16777216 - 32;
5096+
char *large_str = bson_malloc (large_sz);
5097+
for (size_t i = 0; i < large_sz; i++) {
5098+
large_str[i] = 'A';
5099+
}
5100+
large_str[large_sz] = '\0';
5101+
BSON_ASSERT (
5102+
bson_append_utf8 (&large_doc, "key", 3, large_str, large_sz));
5103+
bson_free (large_str);
5104+
}
5105+
5106+
mongoc_client_t *client = test_framework_new_default_client ();
5107+
mongoc_collection_t *coll =
5108+
mongoc_client_get_collection (client, "db", "coll");
5109+
mongoc_bulk_operation_t *bulk =
5110+
mongoc_collection_create_bulk_operation_with_opts (coll, NULL /* opts */);
5111+
size_t added = 0;
5112+
while (added < (size_t) INT_MAX) {
5113+
ok = mongoc_bulk_operation_insert_with_opts (
5114+
bulk, &large_doc, NULL /* opts */, &error);
5115+
ASSERT_OR_PRINT (ok, error);
5116+
added += large_doc.len;
5117+
}
5118+
5119+
ok = (bool) mongoc_bulk_operation_execute (bulk, NULL /* reply */, &error);
5120+
ASSERT_OR_PRINT (ok, error);
5121+
mongoc_bulk_operation_destroy (bulk);
5122+
mongoc_collection_destroy (coll);
5123+
mongoc_client_destroy (client);
5124+
}
5125+
50835126
void
50845127
test_bulk_install (TestSuite *suite)
50855128
{
@@ -5392,4 +5435,7 @@ test_bulk_install (TestSuite *suite)
53925435
TestSuite_AddLive (suite,
53935436
"/BulkOperation/set_client_after_operation",
53945437
test_bulk_write_set_client_after_operation);
5438+
TestSuite_AddLive (suite,
5439+
"/BulkOperation/more_than_INT_MAX",
5440+
test_bulk_write_more_than_INT_MAX);
53955441
}

0 commit comments

Comments
 (0)