Skip to content

Commit d33d253

Browse files
authored
CDRIVER-938 prohibit calling unsafe client setters with pooled clients (#1944)
* log and return on bad calls with a pooled client ** reject a pooled client in `mongoc_client_set_ssl_opts` and `mongoc_client_set_stream_initiator` * fix test calling `mongoc_client_set_stream_initiator` on a pooled client * add doc notices
1 parent 0c3c81b commit d33d253

8 files changed

+89
-7
lines changed

Diff for: NEWS

+2
Original file line numberDiff line numberDiff line change
@@ -44,6 +44,8 @@ Unreleased (2.0.0)
4444
* New behavior: `authMechanismProperties=A:B,C:D:E,F:G` is parsed as `{'A': 'B': 'C': 'D:E', 'F': 'G'}`.
4545
* Calling `mongoc_bulk_operation_execute` on the same `mongoc_bulk_operation_t` repeatedly is an error. Previously this was only discouraged in documentation.
4646
* Consistently apply `__cdecl` calling convention to function declarations in public API. Intended to support consumers building their code using a different [default calling convention](https://learn.microsoft.com/en-us/cpp/build/reference/gd-gr-gv-gz-calling-convention) with MSVC. The mongoc and bson libraries only support being built with the `__cdecl` default calling convention.
47+
* `mongoc_client_set_ssl_opts` now ignores a pooled `mongoc_client_t` and logs an error. Use `mongoc_client_pool_set_ssl_opts` to set TLS options on a `mongoc_client_pool_t` before popping any clients.
48+
* `mongoc_client_set_ssl_stream_initiator` now ignores a pooled `mongoc_client_t` and logs an error.
4749

4850
## Removals
4951

Diff for: src/libmongoc/doc/mongoc_client_set_ssl_opts.rst

+2
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,8 @@ It is a programming error to call this function on a client from a
3232
:symbol:`mongoc_client_pool_set_ssl_opts` on the pool before popping any
3333
clients.
3434

35+
.. versionchanged:: 2.0.0 This function logs an error and immediately returns if ``client`` is from a :symbol:`mongoc_client_pool_t`. Previously this function unsafely applied the options to the pooled client.
36+
3537
Parameters
3638
----------
3739

Diff for: src/libmongoc/doc/mongoc_client_set_stream_initiator.rst

+4
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,10 @@ Synopsis
1515
1616
The :symbol:`mongoc_client_set_stream_initiator()` function shall associate a given :symbol:`mongoc_client_t` with a new stream initiator. This will completely replace the default transport (buffered TCP, possibly with TLS). The ``initiator`` should fulfill the :symbol:`mongoc_stream_t` contract. ``user_data`` is passed through to the ``initiator`` callback and may be used for whatever run time customization is necessary.
1717

18+
It is a programming error to call this function on a :symbol:`mongoc_client_t` from a :symbol:`mongoc_client_pool_t`.
19+
20+
.. versionchanged:: 2.0.0 This function logs an error and immediately returns if ``client`` is from a :symbol:`mongoc_client_pool_t`. Previously this function unsafely applied the initiator to the pooled client.
21+
1822
If ``user_data`` is passed, it is the application's responsibility to ensure ``user_data`` remains valid for the lifetime of the client.
1923

2024
Parameters

Diff for: src/libmongoc/src/mongoc/mongoc-client-pool.c

+2-2
Original file line numberDiff line numberDiff line change
@@ -276,7 +276,7 @@ _initialize_new_client (mongoc_client_pool_t *pool, mongoc_client_t *client)
276276
BSON_ASSERT_PARAM (client);
277277

278278
/* for tests */
279-
mongoc_client_set_stream_initiator (
279+
_mongoc_client_set_stream_initiator_single_or_pooled (
280280
client, pool->topology->scanner->initiator, pool->topology->scanner->initiator_context);
281281

282282
pool->client_initialized = true;
@@ -286,7 +286,7 @@ _initialize_new_client (mongoc_client_pool_t *pool, mongoc_client_t *client)
286286

287287
#ifdef MONGOC_ENABLE_SSL
288288
if (pool->ssl_opts_set) {
289-
mongoc_client_set_ssl_opts (client, &pool->ssl_opts);
289+
_mongoc_client_set_ssl_opts_for_single_or_pooled (client, &pool->ssl_opts);
290290
}
291291
#endif
292292
}

Diff for: src/libmongoc/src/mongoc/mongoc-client-private.h

+8
Original file line numberDiff line numberDiff line change
@@ -229,6 +229,14 @@ mongoc_client_uses_server_api (const mongoc_client_t *client);
229229
bool
230230
mongoc_client_uses_loadbalanced (const mongoc_client_t *client);
231231

232+
void
233+
_mongoc_client_set_ssl_opts_for_single_or_pooled (mongoc_client_t *client, const mongoc_ssl_opt_t *opts);
234+
235+
void
236+
_mongoc_client_set_stream_initiator_single_or_pooled (mongoc_client_t *client,
237+
mongoc_stream_initiator_t initiator,
238+
void *user_data);
239+
232240
BSON_END_DECLS
233241

234242
#endif /* MONGOC_CLIENT_PRIVATE_H */

Diff for: src/libmongoc/src/mongoc/mongoc-client.c

+33-3
Original file line numberDiff line numberDiff line change
@@ -985,7 +985,22 @@ void
985985
mongoc_client_set_ssl_opts (mongoc_client_t *client, const mongoc_ssl_opt_t *opts)
986986
{
987987
BSON_ASSERT_PARAM (client);
988-
BSON_ASSERT (opts);
988+
BSON_ASSERT_PARAM (opts);
989+
990+
if (!client->topology->single_threaded) {
991+
MONGOC_ERROR (
992+
"mongoc_client_set_ssl_opts cannot be called on a pooled client. Use mongoc_client_pool_set_ssl_opts.");
993+
return;
994+
}
995+
996+
_mongoc_client_set_ssl_opts_for_single_or_pooled (client, opts);
997+
}
998+
999+
void
1000+
_mongoc_client_set_ssl_opts_for_single_or_pooled (mongoc_client_t *client, const mongoc_ssl_opt_t *opts)
1001+
{
1002+
BSON_ASSERT_PARAM (client);
1003+
BSON_ASSERT_PARAM (opts);
9891004

9901005
_mongoc_ssl_opts_cleanup (&client->ssl_opts, false /* don't free internal opts */);
9911006

@@ -1003,7 +1018,7 @@ mongoc_client_set_ssl_opts (mongoc_client_t *client, const mongoc_ssl_opt_t *opt
10031018
#endif
10041019
}
10051020
}
1006-
#endif
1021+
#endif // MONGOC_ENABLE_SSL
10071022

10081023

10091024
mongoc_client_t *
@@ -1118,7 +1133,7 @@ _mongoc_client_new_from_topology (mongoc_topology_t *topology)
11181133
_mongoc_ssl_opts_from_uri (&ssl_opt, &internal_tls_opts, client->uri);
11191134
/* sets use_ssl = true */
11201135
/* this call creates an ssl ctx only if single-threaded, otherwise client inherits from pool */
1121-
mongoc_client_set_ssl_opts (client, &ssl_opt);
1136+
_mongoc_client_set_ssl_opts_for_single_or_pooled (client, &ssl_opt);
11221137
_mongoc_client_set_internal_tls_opts (client, &internal_tls_opts);
11231138
}
11241139
#endif
@@ -2226,6 +2241,21 @@ mongoc_client_set_stream_initiator (mongoc_client_t *client, mongoc_stream_initi
22262241
{
22272242
BSON_ASSERT_PARAM (client);
22282243

2244+
if (!client->topology->single_threaded) {
2245+
MONGOC_ERROR ("mongoc_client_set_stream_initiator cannot be called on a pooled client.");
2246+
return;
2247+
}
2248+
2249+
_mongoc_client_set_stream_initiator_single_or_pooled (client, initiator, user_data);
2250+
}
2251+
2252+
void
2253+
_mongoc_client_set_stream_initiator_single_or_pooled (mongoc_client_t *client,
2254+
mongoc_stream_initiator_t initiator,
2255+
void *user_data)
2256+
{
2257+
BSON_ASSERT_PARAM (client);
2258+
22292259
if (!initiator) {
22302260
initiator = mongoc_client_default_stream_initiator;
22312261
user_data = client;

Diff for: src/libmongoc/tests/test-mongoc-client-pool.c

+37-1
Original file line numberDiff line numberDiff line change
@@ -546,7 +546,38 @@ test_mongoc_client_pool_change_openssl_ctx (void)
546546

547547
mongoc_client_pool_destroy (pool);
548548
}
549-
#endif
549+
#endif // MONGOC_ENABLE_SSL_OPENSSL
550+
551+
#if defined(MONGOC_ENABLE_SSL)
552+
static void
553+
test_mongoc_client_set_ssl_opts_on_pool (void)
554+
{
555+
// Test calling `mongoc_client_set_ssl_opts` on a pooled client logs an error.
556+
mongoc_client_pool_t *pool = test_framework_new_default_client_pool ();
557+
mongoc_client_t *client_from_pool = mongoc_client_pool_pop (pool);
558+
capture_logs (true);
559+
mongoc_client_set_ssl_opts (client_from_pool, mongoc_ssl_opt_get_default ());
560+
ASSERT_CAPTURED_LOG ("mongoc_client_set_ssl_opts", MONGOC_LOG_LEVEL_ERROR, "cannot be called on a pooled client");
561+
capture_logs (false);
562+
mongoc_client_pool_push (pool, client_from_pool);
563+
mongoc_client_pool_destroy (pool);
564+
}
565+
#endif // MONGOC_ENABLE_SSL
566+
567+
static void
568+
test_mongoc_client_set_stream_initiator (void)
569+
{
570+
// Test calling `mongoc_client_set_initiator` on a pooled client logs an error.
571+
mongoc_client_pool_t *pool = test_framework_new_default_client_pool ();
572+
mongoc_client_t *client_from_pool = mongoc_client_pool_pop (pool);
573+
capture_logs (true);
574+
mongoc_client_set_stream_initiator (client_from_pool, mongoc_client_default_stream_initiator, NULL);
575+
ASSERT_CAPTURED_LOG (
576+
"mongoc_client_set_stream_initiator", MONGOC_LOG_LEVEL_ERROR, "cannot be called on a pooled client");
577+
capture_logs (false);
578+
mongoc_client_pool_push (pool, client_from_pool);
579+
mongoc_client_pool_destroy (pool);
580+
}
550581

551582
void
552583
test_client_pool_install (TestSuite *suite)
@@ -593,4 +624,9 @@ test_client_pool_install (TestSuite *suite)
593624
#if defined(MONGOC_ENABLE_SSL_OPENSSL)
594625
TestSuite_Add (suite, "/ClientPool/openssl/change_ssl_opts", test_mongoc_client_pool_change_openssl_ctx);
595626
#endif
627+
628+
#if defined(MONGOC_ENABLE_SSL)
629+
TestSuite_AddLive (suite, "/ClientPool/mongoc_client_set_ssl_opts", test_mongoc_client_set_ssl_opts_on_pool);
630+
#endif // MONGOC_ENABLE_SSL
631+
TestSuite_AddLive (suite, "/ClientPool/mongoc_client_set_stream_initiator", test_mongoc_client_set_stream_initiator);
596632
}

Diff for: src/libmongoc/tests/test-mongoc-cluster.c

+1-1
Original file line numberDiff line numberDiff line change
@@ -1322,7 +1322,7 @@ test_hello_on_unknown (void)
13221322

13231323
client = mongoc_client_pool_pop (pool);
13241324

1325-
mongoc_client_set_stream_initiator (client, _initiator_fn, pool);
1325+
_mongoc_client_set_stream_initiator_single_or_pooled (client, _initiator_fn, pool);
13261326

13271327
/* The other client marked the server as unknown after this client selected
13281328
* the server and created a stream, but *before* constructing the initial

0 commit comments

Comments
 (0)