[CDRIVER-4039] Memory leak in mongoc_database_command_simple when passing in a reply object created by bson_new Created: 25/Jun/21  Updated: 27/Oct/23  Resolved: 26/Aug/21

Status: Closed
Project: C Driver
Component/s: None
Affects Version/s: None
Fix Version/s: None

Type: Bug Priority: Unknown
Reporter: Harris Kaufmann Assignee: Kevin Albertson
Resolution: Works as Designed Votes: 0
Labels: post-5.0
Remaining Estimate: Not Specified
Time Spent: Not Specified
Original Estimate: Not Specified

Issue Links:
Related

 Description   

The command `mongoc_database_command_simple` leaks memory, when passing in a reply object created by bson_new. This can easily be reproduced with a few lines on C code: https://gist.github.com/kamulos/92b9a270c9e6e36e512cfa43ec470c26

I found this in a Rust wrapper of libmongoc: https://github.com/appsignal/mongo-rust-driver/issues/70

The only cause I could find is that the `flags` are set to `BSON_FLAG_STATIC` in `bson_copy_to`. This prevents the pointer being freed in `bson_destroy`.
 



 Comments   
Comment by Kevin Albertson [ 26/Aug/21 ]

The command `mongoc_database_command_simple` leaks memory, when passing in a reply object created by bson_new.

The bson_t* reply output argument of mongoc_database_command_simple must be a pointer to an uninitialized bson_t, and cannot be the result of bson_new.

The available options are:

1. Use a bson_t on the stack:

bson_t reply;
bson_t cmd;
mongoc_database_t* db;
bson_error_t err;
 
bson_init (&cmd);
BCON_APPEND (&cmd, "ping", BCON_INT32(1));
db = mongoc_client_get_database (client, "admin");
if (!mongoc_database_command_simple (db, &cmd, NULL /* read prefs */, &reply, &err)) {
   MONGOC_ERROR ("database_command_simple error: %s", err.message);
}
bson_destroy (&cmd);
bson_destroy (&reply);
mongoc_database_destroy (db);

2. Manually heap allocate a bson_t

bson_t* reply;
bson_t cmd;
mongoc_database_t* db;
bson_error_t err;
 
reply = bson_malloc0 (sizeof (bson_t));
bson_init (&cmd);
BCON_APPEND (&cmd, "ping", BCON_INT32(1));
db = mongoc_client_get_database (client, "admin");
if (!mongoc_database_command_simple (db, &cmd, NULL /* read prefs */, reply, &err)) {
   MONGOC_ERROR ("database_command_simple error: %s", err.message);
}
 
bson_destroy (&cmd);
bson_destroy (reply);
bson_free (reply);
mongoc_database_destroy (db);

 
The expectation around how reply should be passed is inconsistently documented. I have updated the description of CDRIVER-3368 to call out mongoc_database_command_simple as one such example.

Comment by Kevin Albertson [ 28/Jun/21 ]

Hello st4ck0v3rfl0w@gmail.com, thank you for the report! We will further investigate this after we have completed high priority work for upcoming server support. Thank you for your patience.

Generated at Wed Feb 07 21:19:45 UTC 2024 using Jira 9.7.1#970001-sha1:2222b88b221c4928ef0de3161136cc90c8356a66.