Commit 25a51c5cac for openssl.org

commit 25a51c5cacbe7b1d1aadb3037a96bdfd09faaf45
Author: Neil Horman <nhorman@openssl.org>
Date:   Tue Jan 13 16:25:21 2026 -0500

    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 <tomas@openssl.org>
    Reviewed-by: Nikola Pajkovsky <nikolap@openssl.org>
    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 192ccbeb91..dcc3201baa 100644
--- a/crypto/bsearch.c
+++ b/crypto/bsearch.c
@@ -10,8 +10,10 @@
 #include <stddef.h>
 #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 ac95d098b9..835e1affae 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 f5daca2aad..e4935b66d2 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 d35348743b..1796239335 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 625d9d12ef..d8a745ad18 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,