Skip to content

CDRIVER-5549 Address -fsanitize=function and -Wcast-function-type-strict warnings #1662

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 14 commits into from
Jul 9, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
13 changes: 12 additions & 1 deletion .evergreen/scripts/run-tests.sh
Original file line number Diff line number Diff line change
Expand Up @@ -114,7 +114,18 @@ fi
export ASAN_OPTIONS="detect_leaks=1 abort_on_error=1 symbolize=1"
export ASAN_SYMBOLIZER_PATH="/opt/mongodbtoolchain/v3/bin/llvm-symbolizer"
export TSAN_OPTIONS="suppressions=./.tsan-suppressions"
export UBSAN_OPTIONS="print_stacktrace=1 abort_on_error=1"

ubsan_opts=(
"print_stacktrace=1"
"abort_on_error=1"
)

# UBSan with Clang 3.8 fails to parse the suppression file.
if [[ "${distro_id:?}" != ubuntu1604-* ]]; then
ubsan_opts+=("suppressions=./.ubsan-suppressions")
fi

export UBSAN_OPTIONS="${ubsan_opts[*]}"

declare -a test_args=(
"-d"
Expand Down
10 changes: 10 additions & 0 deletions .ubsan-suppressions
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
# src/utf8proc-2.8.0/utf8proc.c:368:53: runtime error: applying zero offset to null pointer
# src/utf8proc-2.8.0/utf8proc.c:554:20: runtime error: applying zero offset to null pointer
#
# Upstream Fix: https://github.com/JuliaStrings/utf8proc/pull/240
#
# Context: https://github.com/llvm/llvm-project/commit/536b0ee40ab97f2878dc124a321cf9108ee3d233
# > To make things more fun, in C (6.5.6p8), applying *any* offset to null pointer
# > is undefined, although Clang front-end pessimizes the code by not lowering
# > that info, so this UB is "harmless".
pointer-overflow:utf8proc.c
13 changes: 13 additions & 0 deletions src/common/common-macros-private.h
Original file line number Diff line number Diff line change
Expand Up @@ -42,4 +42,17 @@
#define MC_ENABLE_CONVERSION_WARNING_END
#endif

// Disable the -Wcast-function-type-strict warning.
#define MC_DISABLE_CAST_FUNCTION_TYPE_STRICT_WARNING_BEGIN
#define MC_DISABLE_CAST_FUNCTION_TYPE_STRICT_WARNING_END
#if defined(__clang__)
#if __has_warning("-Wcast-function-type-strict")
#undef MC_DISABLE_CAST_FUNCTION_TYPE_STRICT_WARNING_BEGIN
#undef MC_DISABLE_CAST_FUNCTION_TYPE_STRICT_WARNING_END
#define MC_DISABLE_CAST_FUNCTION_TYPE_STRICT_WARNING_BEGIN \
_Pragma ("clang diagnostic push") _Pragma ("clang diagnostic ignored \"-Wcast-function-type-strict\"")
#define MC_DISABLE_CAST_FUNCTION_TYPE_STRICT_WARNING_END _Pragma ("clang diagnostic pop")
#endif // __has_warning("-Wcast-function-type-strict")
#endif // defined(__clang__)

#endif /* COMMON_MACROS_PRIVATE_H */
2 changes: 1 addition & 1 deletion src/libbson/tests/test-bson-corpus.c
Original file line number Diff line number Diff line change
Expand Up @@ -267,7 +267,7 @@ test_bson_corpus_parse_error (test_bson_parse_error_type_t *test)


static void
test_bson_corpus_cb (bson_t *scenario)
test_bson_corpus_cb (void *scenario)
{
corpus_test (scenario, test_bson_corpus_valid, test_bson_corpus_decode_error, test_bson_corpus_parse_error);
}
Expand Down
2 changes: 2 additions & 0 deletions src/libmongoc/src/mongoc/mongoc-cyrus.c
Original file line number Diff line number Diff line change
Expand Up @@ -173,12 +173,14 @@ _mongoc_cyrus_verifyfile_cb (void *context, const char *file, sasl_verify_type_t
void
_mongoc_cyrus_init (mongoc_cyrus_t *sasl)
{
MC_DISABLE_CAST_FUNCTION_TYPE_STRICT_WARNING_BEGIN
sasl_callback_t callbacks[] = {{SASL_CB_AUTHNAME, SASL_CALLBACK_FN (_mongoc_cyrus_get_user), sasl},
{SASL_CB_USER, SASL_CALLBACK_FN (_mongoc_cyrus_get_user), sasl},
{SASL_CB_PASS, SASL_CALLBACK_FN (_mongoc_cyrus_get_pass), sasl},
{SASL_CB_CANON_USER, SASL_CALLBACK_FN (_mongoc_cyrus_canon_user), sasl},
{SASL_CB_VERIFYFILE, SASL_CALLBACK_FN (_mongoc_cyrus_verifyfile_cb), NULL},
{SASL_CB_LIST_END}};
MC_DISABLE_CAST_FUNCTION_TYPE_STRICT_WARNING_END

BSON_ASSERT (sasl);

Expand Down
2 changes: 2 additions & 0 deletions src/libmongoc/src/mongoc/mongoc-init.c
Original file line number Diff line number Diff line change
Expand Up @@ -111,9 +111,11 @@ static BSON_ONCE_FUN (_mongoc_do_init)
sasl_set_mutex (
mongoc_cyrus_mutex_alloc, mongoc_cyrus_mutex_lock, mongoc_cyrus_mutex_unlock, mongoc_cyrus_mutex_free);

MC_DISABLE_CAST_FUNCTION_TYPE_STRICT_WARNING_BEGIN
sasl_callback_t callbacks[] = {// Include callback to disable loading plugins.
{SASL_CB_VERIFYFILE, SASL_CALLBACK_FN (_mongoc_cyrus_verifyfile_cb), NULL},
{SASL_CB_LIST_END}};
MC_DISABLE_CAST_FUNCTION_TYPE_STRICT_WARNING_END

status = sasl_client_init (callbacks);
BSON_ASSERT (status == SASL_OK);
Expand Down
11 changes: 6 additions & 5 deletions src/libmongoc/src/mongoc/mongoc-set-private.h
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@ typedef void (*mongoc_set_item_dtor) (void *item, void *ctx);
typedef bool (*mongoc_set_for_each_cb_t) (void *item, void *ctx);
typedef bool (*mongoc_set_for_each_const_cb_t) (const void *item, void *ctx);
typedef bool (*mongoc_set_for_each_with_id_cb_t) (uint32_t id, void *item, void *ctx);
typedef bool (*mongoc_set_for_each_with_id_const_cb_t) (uint32_t id, const void *item, void *ctx);

typedef struct {
uint32_t id;
Expand Down Expand Up @@ -92,15 +93,15 @@ mongoc_set_destroy (mongoc_set_t *set);
void
mongoc_set_for_each (mongoc_set_t *set, mongoc_set_for_each_cb_t cb, void *ctx);

static BSON_INLINE void
mongoc_set_for_each_const (const mongoc_set_t *set, mongoc_set_for_each_const_cb_t cb, void *ctx)
{
mongoc_set_for_each ((mongoc_set_t *) set, (mongoc_set_for_each_cb_t) cb, ctx);
}
void
mongoc_set_for_each_const (const mongoc_set_t *set, mongoc_set_for_each_const_cb_t cb, void *ctx);

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

void
mongoc_set_for_each_with_id_const (const mongoc_set_t *set, mongoc_set_for_each_with_id_const_cb_t cb, void *ctx);

/* first item in set for which "cb" returns true */
void *
mongoc_set_find_item (mongoc_set_t *set, mongoc_set_for_each_cb_t cb, void *ctx);
Expand Down
97 changes: 70 additions & 27 deletions src/libmongoc/src/mongoc/mongoc-set.c
Original file line number Diff line number Diff line change
Expand Up @@ -146,32 +146,60 @@ typedef struct {
void *ctx;
} _mongoc_set_for_each_helper_t;


static bool
_mongoc_set_for_each_helper (uint32_t id, void *item, void *ctx)
{
_mongoc_set_for_each_helper_t *helper = (_mongoc_set_for_each_helper_t *) ctx;
_mongoc_set_for_each_helper_t *helper = ctx;

BSON_UNUSED (id);

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


void
mongoc_set_for_each (mongoc_set_t *set, mongoc_set_for_each_cb_t cb, void *ctx)
{
_mongoc_set_for_each_helper_t helper;
helper.cb = cb;
helper.ctx = ctx;
_mongoc_set_for_each_helper_t helper = {
.cb = cb,
.ctx = ctx,
};

mongoc_set_for_each_with_id (set, _mongoc_set_for_each_helper, &helper);
}


typedef struct {
mongoc_set_for_each_const_cb_t cb;
void *ctx;
} _mongoc_set_for_each_const_helper_t;

static bool
_mongoc_set_for_each_const_helper (uint32_t id, const void *item, void *ctx)
{
_mongoc_set_for_each_const_helper_t *helper = ctx;

BSON_UNUSED (id);

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

void
mongoc_set_for_each_const (const mongoc_set_t *set, mongoc_set_for_each_const_cb_t cb, void *ctx)
{
_mongoc_set_for_each_const_helper_t helper = {
.cb = cb,
.ctx = ctx,
};

mongoc_set_for_each_with_id_const (set, _mongoc_set_for_each_const_helper, &helper);
}

void
mongoc_set_for_each_with_id (mongoc_set_t *set, mongoc_set_for_each_with_id_cb_t cb, void *ctx)
{
mongoc_set_item_t *old_set;
BSON_ASSERT_PARAM (set);
BSON_ASSERT_PARAM (cb);
BSON_ASSERT (ctx || true);

BSON_ASSERT (bson_in_range_unsigned (uint32_t, set->items_len));
const uint32_t items_len = (uint32_t) set->items_len;
Expand All @@ -181,46 +209,59 @@ mongoc_set_for_each_with_id (mongoc_set_t *set, mongoc_set_for_each_with_id_cb_t
return;
}

old_set = (mongoc_set_item_t *) bson_malloc (sizeof (*old_set) * items_len);
mongoc_set_item_t *const old_set = bson_malloc (sizeof (*old_set) * items_len);
memcpy (old_set, set->items, sizeof (*old_set) * items_len);

for (uint32_t i = 0u; i < items_len; i++) {
if (!cb (i, old_set[i].item, ctx)) {
void *const item = old_set[i].item;

if (!cb (i, item, ctx)) {
break;
}
}

bson_free (old_set);
}


static mongoc_set_item_t *
_mongoc_set_find (const mongoc_set_t *set, mongoc_set_for_each_const_cb_t cb, void *ctx)
void
mongoc_set_for_each_with_id_const (const mongoc_set_t *set, mongoc_set_for_each_with_id_const_cb_t cb, void *ctx)
{
size_t i;
size_t items_len;
mongoc_set_item_t *item;
BSON_ASSERT_PARAM (set);
BSON_ASSERT_PARAM (cb);
BSON_ASSERT (ctx || true);

items_len = set->items_len;
BSON_ASSERT (bson_in_range_unsigned (uint32_t, set->items_len));
const uint32_t items_len = (uint32_t) set->items_len;

for (i = 0; i < items_len; i++) {
item = &set->items[i];
if (cb (item->item, ctx)) {
return item;
/* prevent undefined behavior of memcpy(NULL) */
if (items_len == 0) {
return;
}

mongoc_set_item_t *const old_set = bson_malloc (sizeof (*old_set) * items_len);
memcpy (old_set, set->items, sizeof (*old_set) * items_len);

for (uint32_t i = 0u; i < items_len; i++) {
const void *const item = old_set[i].item;

if (!cb (i, item, ctx)) {
break;
}
}

return NULL;
bson_free (old_set);
}


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

if ((item = _mongoc_set_find (set, (mongoc_set_for_each_const_cb_t) cb, ctx))) {
return item->item;
if (cb (item->item, ctx)) {
return item;
}
}

return NULL;
Expand All @@ -230,10 +271,12 @@ mongoc_set_find_item (mongoc_set_t *set, mongoc_set_for_each_cb_t cb, void *ctx)
uint32_t
mongoc_set_find_id (const mongoc_set_t *set, mongoc_set_for_each_const_cb_t cb, void *ctx)
{
const mongoc_set_item_t *item;
for (size_t i = 0u; i < set->items_len; i++) {
const mongoc_set_item_t *const item = set->items + i;

if ((item = _mongoc_set_find (set, cb, ctx))) {
return item->id;
if (cb (item->item, ctx)) {
return item->id;
}
}

return 0;
Expand Down
4 changes: 4 additions & 0 deletions src/libmongoc/src/mongoc/mongoc-stream-tls-openssl.c
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,8 @@
#include "mongoc-log.h"
#include "mongoc-error.h"

#include "common-macros-private.h"


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

if (opt->weak_cert_validation) {
Expand Down
15 changes: 9 additions & 6 deletions src/libmongoc/src/mongoc/mongoc-topology.c
Original file line number Diff line number Diff line change
Expand Up @@ -194,26 +194,29 @@ _mongoc_topology_scanner_cb (
}

static void
_server_session_init (mongoc_server_session_t *session, mongoc_topology_t *unused, bson_error_t *error)
_server_session_init (void *session, void *unused, bson_error_t *error)
{
BSON_UNUSED (unused);

_mongoc_server_session_init (session, error);
}

static void
_server_session_destroy (mongoc_server_session_t *session, mongoc_topology_t *unused)
_server_session_destroy (void *session, void *unused)
{
BSON_UNUSED (unused);

_mongoc_server_session_destroy (session);
}

static int
_server_session_should_prune (mongoc_server_session_t *session, mongoc_topology_t *topo)
_server_session_should_prune (const void *session_vp, void *topo_vp)
{
BSON_ASSERT_PARAM (session);
BSON_ASSERT_PARAM (topo);
BSON_ASSERT_PARAM (session_vp);
BSON_ASSERT_PARAM (topo_vp);

const mongoc_server_session_t *const session = session_vp;
mongoc_topology_t *const topo = topo_vp;

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

const mongoc_host_list_t *tmp = hl_array[swap_pos];
hl_array[swap_pos] = hl_array[idx];
Expand Down
Loading