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];