Skip to content

Commit b9e9e1d

Browse files
authored
CDRIVER-5549 Address -fsanitize=function and -Wcast-function-type-strict warnings (#1662)
* Add UBSan suppressions file * Address invocation of TestFuncDtor via Test::dtor * Address invocation of TestFuncWC callbacks via Test::func * Address invocation of TestFunc callbacks via Test::func * Address invocation of CheckFunc via Test::checks * Address invocation of APM callbacks via command_callback_funcs_t * Address invocation of APM callback setters via command_to_cb_t * Address invocation of TS pool callbacks via mongoc_ts_pool_params * Address invocation of callbacks via mongoc_set_t accessors * Address -Wcast-function-type-strict warnings: TestFunc -> make_cursor_fn * Address -Wcast-function-type-strict warnings: TestFunc -> session_test_fn_t * Address -Wcast-function-type-strict warnings: TestFunc -> test_fn * Suppress -Wcast-function-type-strict warnings for external APIs * Address -Wcast-function-type-strict warnings: _mongoc_rand_size_t
1 parent fed2beb commit b9e9e1d

40 files changed

+572
-351
lines changed

.evergreen/scripts/run-tests.sh

Lines changed: 12 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -114,7 +114,18 @@ fi
114114
export ASAN_OPTIONS="detect_leaks=1 abort_on_error=1 symbolize=1"
115115
export ASAN_SYMBOLIZER_PATH="/opt/mongodbtoolchain/v3/bin/llvm-symbolizer"
116116
export TSAN_OPTIONS="suppressions=./.tsan-suppressions"
117-
export UBSAN_OPTIONS="print_stacktrace=1 abort_on_error=1"
117+
118+
ubsan_opts=(
119+
"print_stacktrace=1"
120+
"abort_on_error=1"
121+
)
122+
123+
# UBSan with Clang 3.8 fails to parse the suppression file.
124+
if [[ "${distro_id:?}" != ubuntu1604-* ]]; then
125+
ubsan_opts+=("suppressions=./.ubsan-suppressions")
126+
fi
127+
128+
export UBSAN_OPTIONS="${ubsan_opts[*]}"
118129

119130
declare -a test_args=(
120131
"-d"

.ubsan-suppressions

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
# src/utf8proc-2.8.0/utf8proc.c:368:53: runtime error: applying zero offset to null pointer
2+
# src/utf8proc-2.8.0/utf8proc.c:554:20: runtime error: applying zero offset to null pointer
3+
#
4+
# Upstream Fix: https://github.com/JuliaStrings/utf8proc/pull/240
5+
#
6+
# Context: https://github.com/llvm/llvm-project/commit/536b0ee40ab97f2878dc124a321cf9108ee3d233
7+
# > To make things more fun, in C (6.5.6p8), applying *any* offset to null pointer
8+
# > is undefined, although Clang front-end pessimizes the code by not lowering
9+
# > that info, so this UB is "harmless".
10+
pointer-overflow:utf8proc.c

src/common/common-macros-private.h

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -42,4 +42,17 @@
4242
#define MC_ENABLE_CONVERSION_WARNING_END
4343
#endif
4444

45+
// Disable the -Wcast-function-type-strict warning.
46+
#define MC_DISABLE_CAST_FUNCTION_TYPE_STRICT_WARNING_BEGIN
47+
#define MC_DISABLE_CAST_FUNCTION_TYPE_STRICT_WARNING_END
48+
#if defined(__clang__)
49+
#if __has_warning("-Wcast-function-type-strict")
50+
#undef MC_DISABLE_CAST_FUNCTION_TYPE_STRICT_WARNING_BEGIN
51+
#undef MC_DISABLE_CAST_FUNCTION_TYPE_STRICT_WARNING_END
52+
#define MC_DISABLE_CAST_FUNCTION_TYPE_STRICT_WARNING_BEGIN \
53+
_Pragma ("clang diagnostic push") _Pragma ("clang diagnostic ignored \"-Wcast-function-type-strict\"")
54+
#define MC_DISABLE_CAST_FUNCTION_TYPE_STRICT_WARNING_END _Pragma ("clang diagnostic pop")
55+
#endif // __has_warning("-Wcast-function-type-strict")
56+
#endif // defined(__clang__)
57+
4558
#endif /* COMMON_MACROS_PRIVATE_H */

src/libbson/tests/test-bson-corpus.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -267,7 +267,7 @@ test_bson_corpus_parse_error (test_bson_parse_error_type_t *test)
267267

268268

269269
static void
270-
test_bson_corpus_cb (bson_t *scenario)
270+
test_bson_corpus_cb (void *scenario)
271271
{
272272
corpus_test (scenario, test_bson_corpus_valid, test_bson_corpus_decode_error, test_bson_corpus_parse_error);
273273
}

src/libmongoc/src/mongoc/mongoc-cyrus.c

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -173,12 +173,14 @@ _mongoc_cyrus_verifyfile_cb (void *context, const char *file, sasl_verify_type_t
173173
void
174174
_mongoc_cyrus_init (mongoc_cyrus_t *sasl)
175175
{
176+
MC_DISABLE_CAST_FUNCTION_TYPE_STRICT_WARNING_BEGIN
176177
sasl_callback_t callbacks[] = {{SASL_CB_AUTHNAME, SASL_CALLBACK_FN (_mongoc_cyrus_get_user), sasl},
177178
{SASL_CB_USER, SASL_CALLBACK_FN (_mongoc_cyrus_get_user), sasl},
178179
{SASL_CB_PASS, SASL_CALLBACK_FN (_mongoc_cyrus_get_pass), sasl},
179180
{SASL_CB_CANON_USER, SASL_CALLBACK_FN (_mongoc_cyrus_canon_user), sasl},
180181
{SASL_CB_VERIFYFILE, SASL_CALLBACK_FN (_mongoc_cyrus_verifyfile_cb), NULL},
181182
{SASL_CB_LIST_END}};
183+
MC_DISABLE_CAST_FUNCTION_TYPE_STRICT_WARNING_END
182184

183185
BSON_ASSERT (sasl);
184186

src/libmongoc/src/mongoc/mongoc-init.c

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -111,9 +111,11 @@ static BSON_ONCE_FUN (_mongoc_do_init)
111111
sasl_set_mutex (
112112
mongoc_cyrus_mutex_alloc, mongoc_cyrus_mutex_lock, mongoc_cyrus_mutex_unlock, mongoc_cyrus_mutex_free);
113113

114+
MC_DISABLE_CAST_FUNCTION_TYPE_STRICT_WARNING_BEGIN
114115
sasl_callback_t callbacks[] = {// Include callback to disable loading plugins.
115116
{SASL_CB_VERIFYFILE, SASL_CALLBACK_FN (_mongoc_cyrus_verifyfile_cb), NULL},
116117
{SASL_CB_LIST_END}};
118+
MC_DISABLE_CAST_FUNCTION_TYPE_STRICT_WARNING_END
117119

118120
status = sasl_client_init (callbacks);
119121
BSON_ASSERT (status == SASL_OK);

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

Lines changed: 6 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,7 @@ typedef void (*mongoc_set_item_dtor) (void *item, void *ctx);
2929
typedef bool (*mongoc_set_for_each_cb_t) (void *item, void *ctx);
3030
typedef bool (*mongoc_set_for_each_const_cb_t) (const void *item, void *ctx);
3131
typedef bool (*mongoc_set_for_each_with_id_cb_t) (uint32_t id, void *item, void *ctx);
32+
typedef bool (*mongoc_set_for_each_with_id_const_cb_t) (uint32_t id, const void *item, void *ctx);
3233

3334
typedef struct {
3435
uint32_t id;
@@ -92,15 +93,15 @@ mongoc_set_destroy (mongoc_set_t *set);
9293
void
9394
mongoc_set_for_each (mongoc_set_t *set, mongoc_set_for_each_cb_t cb, void *ctx);
9495

95-
static BSON_INLINE void
96-
mongoc_set_for_each_const (const mongoc_set_t *set, mongoc_set_for_each_const_cb_t cb, void *ctx)
97-
{
98-
mongoc_set_for_each ((mongoc_set_t *) set, (mongoc_set_for_each_cb_t) cb, ctx);
99-
}
96+
void
97+
mongoc_set_for_each_const (const mongoc_set_t *set, mongoc_set_for_each_const_cb_t cb, void *ctx);
10098

10199
void
102100
mongoc_set_for_each_with_id (mongoc_set_t *set, mongoc_set_for_each_with_id_cb_t cb, void *ctx);
103101

102+
void
103+
mongoc_set_for_each_with_id_const (const mongoc_set_t *set, mongoc_set_for_each_with_id_const_cb_t cb, void *ctx);
104+
104105
/* first item in set for which "cb" returns true */
105106
void *
106107
mongoc_set_find_item (mongoc_set_t *set, mongoc_set_for_each_cb_t cb, void *ctx);

src/libmongoc/src/mongoc/mongoc-set.c

Lines changed: 70 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -146,32 +146,60 @@ typedef struct {
146146
void *ctx;
147147
} _mongoc_set_for_each_helper_t;
148148

149-
150149
static bool
151150
_mongoc_set_for_each_helper (uint32_t id, void *item, void *ctx)
152151
{
153-
_mongoc_set_for_each_helper_t *helper = (_mongoc_set_for_each_helper_t *) ctx;
152+
_mongoc_set_for_each_helper_t *helper = ctx;
154153

155154
BSON_UNUSED (id);
156155

157156
return helper->cb (item, helper->ctx);
158157
}
159158

160-
161159
void
162160
mongoc_set_for_each (mongoc_set_t *set, mongoc_set_for_each_cb_t cb, void *ctx)
163161
{
164-
_mongoc_set_for_each_helper_t helper;
165-
helper.cb = cb;
166-
helper.ctx = ctx;
162+
_mongoc_set_for_each_helper_t helper = {
163+
.cb = cb,
164+
.ctx = ctx,
165+
};
167166

168167
mongoc_set_for_each_with_id (set, _mongoc_set_for_each_helper, &helper);
169168
}
170169

170+
171+
typedef struct {
172+
mongoc_set_for_each_const_cb_t cb;
173+
void *ctx;
174+
} _mongoc_set_for_each_const_helper_t;
175+
176+
static bool
177+
_mongoc_set_for_each_const_helper (uint32_t id, const void *item, void *ctx)
178+
{
179+
_mongoc_set_for_each_const_helper_t *helper = ctx;
180+
181+
BSON_UNUSED (id);
182+
183+
return helper->cb (item, helper->ctx);
184+
}
185+
186+
void
187+
mongoc_set_for_each_const (const mongoc_set_t *set, mongoc_set_for_each_const_cb_t cb, void *ctx)
188+
{
189+
_mongoc_set_for_each_const_helper_t helper = {
190+
.cb = cb,
191+
.ctx = ctx,
192+
};
193+
194+
mongoc_set_for_each_with_id_const (set, _mongoc_set_for_each_const_helper, &helper);
195+
}
196+
171197
void
172198
mongoc_set_for_each_with_id (mongoc_set_t *set, mongoc_set_for_each_with_id_cb_t cb, void *ctx)
173199
{
174-
mongoc_set_item_t *old_set;
200+
BSON_ASSERT_PARAM (set);
201+
BSON_ASSERT_PARAM (cb);
202+
BSON_ASSERT (ctx || true);
175203

176204
BSON_ASSERT (bson_in_range_unsigned (uint32_t, set->items_len));
177205
const uint32_t items_len = (uint32_t) set->items_len;
@@ -181,46 +209,59 @@ mongoc_set_for_each_with_id (mongoc_set_t *set, mongoc_set_for_each_with_id_cb_t
181209
return;
182210
}
183211

184-
old_set = (mongoc_set_item_t *) bson_malloc (sizeof (*old_set) * items_len);
212+
mongoc_set_item_t *const old_set = bson_malloc (sizeof (*old_set) * items_len);
185213
memcpy (old_set, set->items, sizeof (*old_set) * items_len);
186214

187215
for (uint32_t i = 0u; i < items_len; i++) {
188-
if (!cb (i, old_set[i].item, ctx)) {
216+
void *const item = old_set[i].item;
217+
218+
if (!cb (i, item, ctx)) {
189219
break;
190220
}
191221
}
192222

193223
bson_free (old_set);
194224
}
195225

196-
197-
static mongoc_set_item_t *
198-
_mongoc_set_find (const mongoc_set_t *set, mongoc_set_for_each_const_cb_t cb, void *ctx)
226+
void
227+
mongoc_set_for_each_with_id_const (const mongoc_set_t *set, mongoc_set_for_each_with_id_const_cb_t cb, void *ctx)
199228
{
200-
size_t i;
201-
size_t items_len;
202-
mongoc_set_item_t *item;
229+
BSON_ASSERT_PARAM (set);
230+
BSON_ASSERT_PARAM (cb);
231+
BSON_ASSERT (ctx || true);
203232

204-
items_len = set->items_len;
233+
BSON_ASSERT (bson_in_range_unsigned (uint32_t, set->items_len));
234+
const uint32_t items_len = (uint32_t) set->items_len;
205235

206-
for (i = 0; i < items_len; i++) {
207-
item = &set->items[i];
208-
if (cb (item->item, ctx)) {
209-
return item;
236+
/* prevent undefined behavior of memcpy(NULL) */
237+
if (items_len == 0) {
238+
return;
239+
}
240+
241+
mongoc_set_item_t *const old_set = bson_malloc (sizeof (*old_set) * items_len);
242+
memcpy (old_set, set->items, sizeof (*old_set) * items_len);
243+
244+
for (uint32_t i = 0u; i < items_len; i++) {
245+
const void *const item = old_set[i].item;
246+
247+
if (!cb (i, item, ctx)) {
248+
break;
210249
}
211250
}
212251

213-
return NULL;
252+
bson_free (old_set);
214253
}
215254

216255

217256
void *
218257
mongoc_set_find_item (mongoc_set_t *set, mongoc_set_for_each_cb_t cb, void *ctx)
219258
{
220-
mongoc_set_item_t *item;
259+
for (size_t i = 0u; i < set->items_len; i++) {
260+
mongoc_set_item_t *const item = set->items + i;
221261

222-
if ((item = _mongoc_set_find (set, (mongoc_set_for_each_const_cb_t) cb, ctx))) {
223-
return item->item;
262+
if (cb (item->item, ctx)) {
263+
return item;
264+
}
224265
}
225266

226267
return NULL;
@@ -230,10 +271,12 @@ mongoc_set_find_item (mongoc_set_t *set, mongoc_set_for_each_cb_t cb, void *ctx)
230271
uint32_t
231272
mongoc_set_find_id (const mongoc_set_t *set, mongoc_set_for_each_const_cb_t cb, void *ctx)
232273
{
233-
const mongoc_set_item_t *item;
274+
for (size_t i = 0u; i < set->items_len; i++) {
275+
const mongoc_set_item_t *const item = set->items + i;
234276

235-
if ((item = _mongoc_set_find (set, cb, ctx))) {
236-
return item->id;
277+
if (cb (item->item, ctx)) {
278+
return item->id;
279+
}
237280
}
238281

239282
return 0;

src/libmongoc/src/mongoc/mongoc-stream-tls-openssl.c

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -41,6 +41,8 @@
4141
#include "mongoc-log.h"
4242
#include "mongoc-error.h"
4343

44+
#include "common-macros-private.h"
45+
4446

4547
#undef MONGOC_LOG_DOMAIN
4648
#define MONGOC_LOG_DOMAIN "stream-tls-openssl"
@@ -759,7 +761,9 @@ mongoc_stream_tls_openssl_new (mongoc_stream_t *base_stream, const char *host, m
759761
if (!client) {
760762
/* Only used by the Mock Server.
761763
* Set a callback to get the SNI, if provided */
764+
MC_DISABLE_CAST_FUNCTION_TYPE_STRICT_WARNING_BEGIN
762765
SSL_CTX_set_tlsext_servername_callback (ssl_ctx, _mongoc_stream_tls_openssl_sni);
766+
MC_DISABLE_CAST_FUNCTION_TYPE_STRICT_WARNING_END
763767
}
764768

765769
if (opt->weak_cert_validation) {

src/libmongoc/src/mongoc/mongoc-topology.c

Lines changed: 9 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -194,26 +194,29 @@ _mongoc_topology_scanner_cb (
194194
}
195195

196196
static void
197-
_server_session_init (mongoc_server_session_t *session, mongoc_topology_t *unused, bson_error_t *error)
197+
_server_session_init (void *session, void *unused, bson_error_t *error)
198198
{
199199
BSON_UNUSED (unused);
200200

201201
_mongoc_server_session_init (session, error);
202202
}
203203

204204
static void
205-
_server_session_destroy (mongoc_server_session_t *session, mongoc_topology_t *unused)
205+
_server_session_destroy (void *session, void *unused)
206206
{
207207
BSON_UNUSED (unused);
208208

209209
_mongoc_server_session_destroy (session);
210210
}
211211

212212
static int
213-
_server_session_should_prune (mongoc_server_session_t *session, mongoc_topology_t *topo)
213+
_server_session_should_prune (const void *session_vp, void *topo_vp)
214214
{
215-
BSON_ASSERT_PARAM (session);
216-
BSON_ASSERT_PARAM (topo);
215+
BSON_ASSERT_PARAM (session_vp);
216+
BSON_ASSERT_PARAM (topo_vp);
217+
218+
const mongoc_server_session_t *const session = session_vp;
219+
mongoc_topology_t *const topo = topo_vp;
217220

218221
/** If "dirty" (i.e. contains a network error), it should be dropped */
219222
if (session->dirty) {
@@ -282,7 +285,7 @@ _mongoc_apply_srv_max_hosts (const mongoc_host_list_t *hl, size_t max_hosts, siz
282285
* Drivers SHOULD use the `Fisher-Yates shuffle` for randomization. */
283286
for (size_t idx = hl_size - 1u; idx > 0u; --idx) {
284287
/* 0 <= swap_pos <= idx */
285-
const size_t swap_pos = _mongoc_rand_size_t (0u, idx, _mongoc_simple_rand_size_t);
288+
const size_t swap_pos = _mongoc_rand_size_t (0u, idx);
286289

287290
const mongoc_host_list_t *tmp = hl_array[swap_pos];
288291
hl_array[swap_pos] = hl_array[idx];

0 commit comments

Comments
 (0)