Commit 69fb9335ee for openssl.org

commit 69fb9335ee0f5dd39aabca6d35d1557ca3b2d856
Author: Neil Horman <nhorman@openssl.org>
Date:   Tue Mar 3 14:47:00 2026 -0500

    Fix bad length computation in HT_COPY_RAW_KEY_CASE

    The new HT_KEY_COPY_RAW fails to account for copy lengths that exceed
    the size of the configured buffer in a key, leading to stack overruns on
    read.

    Rectify that by claming the COPY macro to limit copies to the size of
    the buffer

    Reviewed-by: Paul Dale <paul.dale@oracle.com>
    Reviewed-by: Nikola Pajkovsky <nikolap@openssl.org>
    MergeDate: Wed Mar  4 07:04:07 2026
    (Merged from https://github.com/openssl/openssl/pull/30257)

diff --git a/crypto/core_namemap.c b/crypto/core_namemap.c
index 32e11e6ab9..cf6f363a51 100644
--- a/crypto/core_namemap.c
+++ b/crypto/core_namemap.c
@@ -154,7 +154,7 @@ int ossl_namemap_name2num(const OSSL_NAMEMAP *namemap, const char *name)
         return 0;

     HT_INIT_RAW_KEY(&key);
-    HT_COPY_RAW_KEY_CASE(TO_HT_KEY(&key), name, (int)strlen(name));
+    HT_COPY_RAW_KEY_CASE(TO_HT_KEY(&key), name, strlen(name));

     val = ossl_ht_get(namemap->namenum_ht, TO_HT_KEY(&key));

@@ -184,7 +184,7 @@ int ossl_namemap_name2num_n(const OSSL_NAMEMAP *namemap,
         name_len = NAMEMAP_NAME_LEN;

     HT_INIT_RAW_KEY(&key);
-    HT_COPY_RAW_KEY_CASE(TO_HT_KEY(&key), name, (int)name_len);
+    HT_COPY_RAW_KEY_CASE(TO_HT_KEY(&key), name, name_len);

     val = ossl_ht_get(namemap->namenum_ht, TO_HT_KEY(&key));

@@ -276,7 +276,7 @@ static int namemap_add_name(OSSL_NAMEMAP *namemap, int number,
     tsan_store(&namemap->max_number, number);

     HT_INIT_RAW_KEY(&key);
-    HT_COPY_RAW_KEY_CASE(TO_HT_KEY(&key), name, (int)strlen(name));
+    HT_COPY_RAW_KEY_CASE(TO_HT_KEY(&key), name, strlen(name));

     val.value = (void *)(intptr_t)number;
     ret = ossl_ht_insert(namemap->namenum_ht, TO_HT_KEY(&key), &val, NULL);
diff --git a/include/internal/hashtable.h b/include/internal/hashtable.h
index 5147aa374e..75b5c66b06 100644
--- a/include/internal/hashtable.h
+++ b/include/internal/hashtable.h
@@ -160,10 +160,13 @@ static ossl_inline ossl_unused int ossl_key_raw_copy(HT_KEY *key, const uint8_t
  * Similar to HT_COPY_RAW_KEY but accepts a character buffer, and copies
  * data while converting case for case insensitive matches
  */
-#define HT_COPY_RAW_KEY_CASE(key, buf, len)                                         \
-    do {                                                                            \
-        ossl_ht_strcase((key), (char *)&((key)->keybuf[(key)->keysize]), buf, len); \
-        (key)->keysize += len;                                                      \
+#define HT_COPY_RAW_KEY_CASE(key, buf, len)                                            \
+    do {                                                                               \
+        size_t tmplen = (size_t)(len);                                                 \
+        if (tmplen > (key)->bufsize - (key)->keysize)                                  \
+            tmplen = (key)->bufsize - (key)->keysize;                                  \
+        ossl_ht_strcase((key), (char *)&((key)->keybuf[(key)->keysize]), buf, tmplen); \
+        (key)->keysize += tmplen;                                                      \
     } while (0)

 /*
@@ -313,9 +316,9 @@ static ossl_inline ossl_unused int ossl_key_raw_copy(HT_KEY *key, const uint8_t
 /*
  * Helper function to construct case insensitive keys
  */
-static ossl_inline ossl_unused void ossl_ht_strcase(HT_KEY *key, char *tgt, const char *src, int len)
+static ossl_inline ossl_unused void ossl_ht_strcase(HT_KEY *key, char *tgt, const char *src, size_t len)
 {
-    int i;
+    size_t i;
 #if defined(CHARSET_EBCDIC) && !defined(CHARSET_EBCDIC_TEST)
     const long int case_adjust = ~0x40;
 #else
@@ -331,7 +334,7 @@ static ossl_inline ossl_unused void ossl_ht_strcase(HT_KEY *key, char *tgt, cons
      * we copy more space than we have available
      */
     if (key != NULL && key->keysize + len > key->bufsize)
-        len = (int)(key->bufsize - key->keysize);
+        len = (size_t)(key->bufsize - key->keysize);

     for (i = 0; src[i] != '\0' && i < len; i++)
         tgt[i] = case_adjust & src[i];