Skip to content

Commit 507f78b

Browse files
committed
Protect pooled clients against later API changes
1 parent 06b4fa6 commit 507f78b

File tree

5 files changed

+54
-2
lines changed

5 files changed

+54
-2
lines changed

src/libmongoc/src/mongoc/mongoc-client-pool.c

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -245,6 +245,7 @@ _initialize_new_client (mongoc_client_pool_t *pool, mongoc_client_t *client)
245245
client, &pool->apm_callbacks, pool->apm_context);
246246

247247
client->api = mongoc_server_api_copy (pool->api);
248+
client->api_set = true;
248249

249250
#ifdef MONGOC_ENABLE_SSL
250251
if (pool->ssl_opts_set) {
@@ -528,6 +529,14 @@ mongoc_client_pool_set_server_api (mongoc_client_pool_t *pool,
528529
return false;
529530
}
530531

532+
if (mongoc_client_pool_get_size (pool)) {
533+
bson_set_error (error,
534+
MONGOC_ERROR_POOL,
535+
MONGOC_ERROR_POOL_API_TOO_LATE,
536+
"Cannot set server api after a client has been created");
537+
return false;
538+
}
539+
531540
pool->api = mongoc_server_api_copy (api);
532541
_mongoc_topology_scanner_set_server_api (pool->topology->scanner, api);
533542
return true;

src/libmongoc/src/mongoc/mongoc-client-private.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -119,6 +119,7 @@ struct _mongoc_client_t {
119119
bool error_api_set;
120120

121121
mongoc_server_api_t *api;
122+
bool api_set;
122123

123124
/* mongoc_client_session_t's in use, to look up lsids and clusterTimes */
124125
mongoc_set_t *client_sessions;

src/libmongoc/src/mongoc/mongoc-client.c

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3105,7 +3105,7 @@ mongoc_client_set_server_api (mongoc_client_t *client,
31053105
BSON_ASSERT_PARAM (client);
31063106
BSON_ASSERT_PARAM (api);
31073107

3108-
if (client->api) {
3108+
if (client->api_set) {
31093109
bson_set_error (error,
31103110
MONGOC_ERROR_CLIENT,
31113111
MONGOC_ERROR_CLIENT_API_ALREADY_SET,
@@ -3114,6 +3114,7 @@ mongoc_client_set_server_api (mongoc_client_t *client,
31143114
}
31153115

31163116
client->api = mongoc_server_api_copy (api);
3117+
client->api_set = true;
31173118
_mongoc_topology_scanner_set_server_api (client->topology->scanner, api);
31183119
return true;
31193120
}

src/libmongoc/src/mongoc/mongoc-error.h

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -130,7 +130,8 @@ typedef enum {
130130

131131
/* An error related to server version api */
132132
MONGOC_ERROR_CLIENT_API_ALREADY_SET,
133-
MONGOC_ERROR_POOL_API_ALREADY_SET
133+
MONGOC_ERROR_POOL_API_ALREADY_SET,
134+
MONGOC_ERROR_POOL_API_TOO_LATE
134135
} mongoc_error_code_t;
135136

136137
MONGOC_EXPORT (bool)

src/libmongoc/tests/test-mongoc-versioned-api.c

Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -135,6 +135,43 @@ _test_mongoc_server_api_client_pool (void)
135135
mongoc_uri_destroy (uri);
136136
}
137137

138+
static void
139+
_test_mongoc_server_api_client_pool_once (void)
140+
{
141+
mongoc_uri_t *uri;
142+
mongoc_client_pool_t *pool;
143+
mongoc_client_t *client;
144+
mongoc_server_api_t *api;
145+
bson_error_t error;
146+
147+
uri = mongoc_uri_new ("mongodb://localhost");
148+
pool = mongoc_client_pool_new (uri);
149+
150+
api = mongoc_server_api_new (MONGOC_SERVER_API_V1);
151+
152+
client = mongoc_client_pool_pop (pool);
153+
BSON_ASSERT (!client->api);
154+
155+
/* Cannot change server API once a client has been popped. */
156+
ASSERT (!mongoc_client_pool_set_server_api (pool, api, &error));
157+
ASSERT_ERROR_CONTAINS (
158+
error,
159+
MONGOC_ERROR_POOL,
160+
MONGOC_ERROR_POOL_API_TOO_LATE,
161+
"Cannot set server api after a client has been created");
162+
163+
ASSERT (!mongoc_client_set_server_api (client, api, &error));
164+
ASSERT_ERROR_CONTAINS (error,
165+
MONGOC_ERROR_CLIENT,
166+
MONGOC_ERROR_CLIENT_API_ALREADY_SET,
167+
"Cannot set server api more than once");
168+
169+
mongoc_client_pool_push (pool, client);
170+
mongoc_client_pool_destroy (pool);
171+
mongoc_server_api_destroy (api);
172+
mongoc_uri_destroy (uri);
173+
}
174+
138175
void
139176
test_client_versioned_api_install (TestSuite *suite)
140177
{
@@ -144,6 +181,9 @@ test_client_versioned_api_install (TestSuite *suite)
144181
suite, "/VersionedApi/client", _test_mongoc_server_api_client);
145182
TestSuite_Add (
146183
suite, "/VersionedApi/client_pool", _test_mongoc_server_api_client_pool);
184+
TestSuite_Add (suite,
185+
"/VersionedApi/client_pool_once",
186+
_test_mongoc_server_api_client_pool_once);
147187
TestSuite_Add (suite, "/VersionedApi/copy", _test_mongoc_server_api_copy);
148188
TestSuite_Add (
149189
suite, "/VersionedApi/setters", _test_mongoc_server_api_setters);

0 commit comments

Comments
 (0)