From: Neil Horman Date: Tue, 13 Jan 2026 21:25:21 +0000 (-0500) Subject: add cmp_thunk function to ossl_bsearch X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=25a51c5cacbe7b1d1aadb3037a96bdfd09faaf45;p=thirdparty%2Fopenssl.git add cmp_thunk function to ossl_bsearch Add the initial groundwork to allow for the use of a thunking function with bsearch. Normally our comparison function signature doesn't match the type of the pointer we call it through, leading to ubsan errors, this lets those signatures match and gives us a place to do the proper casting Reviewed-by: Tomas Mraz Reviewed-by: Nikola Pajkovsky MergeDate: Sat Feb 7 18:11:11 2026 (Merged from https://github.com/openssl/openssl/pull/29640) --- diff --git a/crypto/bsearch.c b/crypto/bsearch.c index 192ccbeb916..dcc3201baa8 100644 --- a/crypto/bsearch.c +++ b/crypto/bsearch.c @@ -10,8 +10,10 @@ #include #include "internal/cryptlib.h" +typedef int (*cmpthunk_fn)(const void *, const void *); const void *ossl_bsearch(const void *key, const void *base, int num, int size, int (*cmp)(const void *, const void *), + int (*cmp_thunk)(cmpthunk_fn real_cmp_fn, const void *, const void *), int flags) { const char *base_ = base; @@ -25,7 +27,10 @@ const void *ossl_bsearch(const void *key, const void *base, int num, while (l < h) { i = (l + h) / 2; p = &(base_[i * size]); - c = (*cmp)(key, p); + if (cmp_thunk != NULL) + c = cmp_thunk((cmpthunk_fn)cmp, key, (const void *)p); + else + c = cmp(key, p); if (c < 0) h = i; else if (c > 0) @@ -36,8 +41,16 @@ const void *ossl_bsearch(const void *key, const void *base, int num, if (c != 0 && !(flags & OSSL_BSEARCH_VALUE_ON_NOMATCH)) p = NULL; else if (c == 0 && (flags & OSSL_BSEARCH_FIRST_VALUE_ON_MATCH)) { - while (i > 0 && (*cmp)(key, &(base_[(i - 1) * size])) == 0) + while (i > 0) { + if (cmp_thunk != NULL) { + if (cmp_thunk((cmpthunk_fn)cmp, key, (const void *)&(base_[(i - 1) * size]))) + break; + } else { + if (cmp(key, &(base_[(i - 1) * size]))) + break; + } i--; + } p = &(base_[i * size]); } return p; diff --git a/crypto/objects/obj_dat.c b/crypto/objects/obj_dat.c index ac95d098b9c..835e1affae6 100644 --- a/crypto/objects/obj_dat.c +++ b/crypto/objects/obj_dat.c @@ -618,7 +618,7 @@ const void *OBJ_bsearch_ex_(const void *key, const void *base, int num, int (*cmp)(const void *, const void *), int flags) { - const char *p = ossl_bsearch(key, base, num, size, cmp, flags); + const char *p = ossl_bsearch(key, base, num, size, cmp, NULL, flags); #ifdef CHARSET_EBCDIC /* diff --git a/crypto/property/property_query.c b/crypto/property/property_query.c index f5daca2aad1..e4935b66d29 100644 --- a/crypto/property/property_query.c +++ b/crypto/property/property_query.c @@ -30,7 +30,7 @@ ossl_property_find_property(const OSSL_PROPERTY_LIST *list, return NULL; return ossl_bsearch(&name_idx, list->properties, list->num_properties, - sizeof(*list->properties), &property_idx_cmp, 0); + sizeof(*list->properties), &property_idx_cmp, NULL, 0); } OSSL_PROPERTY_TYPE ossl_property_get_type(const OSSL_PROPERTY_DEFINITION *prop) diff --git a/crypto/stack/stack.c b/crypto/stack/stack.c index d35348743bf..17962393356 100644 --- a/crypto/stack/stack.c +++ b/crypto/stack/stack.c @@ -359,7 +359,7 @@ static int internal_find(const OPENSSL_STACK *st, const void *data, if (pnum_matched != NULL) ret_val_options |= OSSL_BSEARCH_FIRST_VALUE_ON_MATCH; - r = ossl_bsearch(&data, st->data, st->num, sizeof(void *), st->comp, + r = ossl_bsearch(&data, st->data, st->num, sizeof(void *), st->comp, NULL, ret_val_options); if (pnum_matched != NULL) { diff --git a/include/internal/cryptlib.h b/include/internal/cryptlib.h index 625d9d12ef2..d8a745ad189 100644 --- a/include/internal/cryptlib.h +++ b/include/internal/cryptlib.h @@ -151,6 +151,7 @@ int ossl_crypto_free_ex_index_ex(OSSL_LIB_CTX *ctx, int class_index, int idx); const void *ossl_bsearch(const void *key, const void *base, int num, int size, int (*cmp)(const void *, const void *), + int (*cmp_thunk)(int (*real_cmp_fn)(const void *, const void *), const void *, const void *), int flags); char *ossl_sk_ASN1_UTF8STRING2text(STACK_OF(ASN1_UTF8STRING) *text,