From 4ac448042c590cda46ff9f94be89c4fa62dd70f7 Mon Sep 17 00:00:00 2001 From: Gordon Ross Date: Fri, 20 Feb 2026 23:25:21 -0500 Subject: [PATCH 1/3] Fix x509-store for illumos Can't use sizof(d->d_name) Use NAME_MAX or MAXNAMLEN --- .../pal_x509.c | 24 +++++++++++++++---- 1 file changed, 19 insertions(+), 5 deletions(-) diff --git a/src/native/libs/System.Security.Cryptography.Native/pal_x509.c b/src/native/libs/System.Security.Cryptography.Native/pal_x509.c index 6e47436f8a662d..3a4500d1e58f77 100644 --- a/src/native/libs/System.Security.Cryptography.Native/pal_x509.c +++ b/src/native/libs/System.Security.Cryptography.Native/pal_x509.c @@ -445,12 +445,20 @@ static DIR* OpenUserStore(const char* storePath, char** pathTmp, size_t* pathTmp return NULL; } - struct dirent* ent = NULL; size_t storePathLen = strlen(storePath); - // d_name is a fixed length char[], not a char*. - // Leave one byte for '\0' and one for '/' - size_t allocSize = storePathLen + sizeof(ent->d_name) + 2; + // Allocate enough space for the store path, a '/', the maximum filename length, and a null terminator + // On some platforms (like illumos), d_name is declared as char[1], so sizeof(d_name) doesn't give + // the actual maximum length. Use NAME_MAX or MAXNAMLEN instead. +#ifdef NAME_MAX + size_t maxNameLen = NAME_MAX; +#elif defined(MAXNAMLEN) + size_t maxNameLen = MAXNAMLEN; +#else + size_t maxNameLen = 255; // Reasonable default +#endif + + size_t allocSize = storePathLen + maxNameLen + 2; // +2 for '/' and '\0' char* tmp = (char*)calloc(allocSize, sizeof(char)); if (!tmp) { @@ -480,10 +488,16 @@ static X509* ReadNextPublicCert(DIR* dir, X509Stack* tmpStack, char* pathTmp, si while ((next = readdir(dir)) != NULL) { - size_t len = strnlen(next->d_name, sizeof(next->d_name)); + size_t len = strlen(next->d_name); if (len > 4 && 0 == strncasecmp(".pfx", next->d_name + len - 4, 4)) { + if (len >= remaining) + { + // Filename too long for buffer, skip it + continue; + } + memcpy_s(nextFileWrite, remaining, next->d_name, len); // if d_name was full-length it might not have a trailing null. nextFileWrite[len] = 0; From ad6a43847e1c87ca9b76a0cee9a674664b5041ff Mon Sep 17 00:00:00 2001 From: Gordon Ross Date: Wed, 25 Feb 2026 09:06:40 -0500 Subject: [PATCH 2/3] review 1: includes, strnlen --- .../pal_x509.c | 20 +++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) diff --git a/src/native/libs/System.Security.Cryptography.Native/pal_x509.c b/src/native/libs/System.Security.Cryptography.Native/pal_x509.c index 3a4500d1e58f77..7cd3c13f5897df 100644 --- a/src/native/libs/System.Security.Cryptography.Native/pal_x509.c +++ b/src/native/libs/System.Security.Cryptography.Native/pal_x509.c @@ -6,6 +6,7 @@ #include "../Common/pal_safecrt.h" #include #include +#include #include #include #include @@ -434,6 +435,14 @@ X509* CryptoNative_X509UpRef(X509* x509) return x509; } +// On some platforms (like illumos), d_name is declared as char[1], so sizeof(d_name) doesn't give +// the actual maximum length. Use NAME_MAX or MAXNAMLEN instead. +#ifdef NAME_MAX +static size_t maxNameLen = NAME_MAX; +#else +static size_t maxNameLen = 255; // Reasonable default +#endif + static DIR* OpenUserStore(const char* storePath, char** pathTmp, size_t* pathTmpSize, char** nextFileWrite) { DIR* trustDir = opendir(storePath); @@ -448,15 +457,6 @@ static DIR* OpenUserStore(const char* storePath, char** pathTmp, size_t* pathTmp size_t storePathLen = strlen(storePath); // Allocate enough space for the store path, a '/', the maximum filename length, and a null terminator - // On some platforms (like illumos), d_name is declared as char[1], so sizeof(d_name) doesn't give - // the actual maximum length. Use NAME_MAX or MAXNAMLEN instead. -#ifdef NAME_MAX - size_t maxNameLen = NAME_MAX; -#elif defined(MAXNAMLEN) - size_t maxNameLen = MAXNAMLEN; -#else - size_t maxNameLen = 255; // Reasonable default -#endif size_t allocSize = storePathLen + maxNameLen + 2; // +2 for '/' and '\0' char* tmp = (char*)calloc(allocSize, sizeof(char)); @@ -488,7 +488,7 @@ static X509* ReadNextPublicCert(DIR* dir, X509Stack* tmpStack, char* pathTmp, si while ((next = readdir(dir)) != NULL) { - size_t len = strlen(next->d_name); + size_t len = strnlen(next->d_name, maxNameLen); if (len > 4 && 0 == strncasecmp(".pfx", next->d_name + len - 4, 4)) { From 89ce67964162f9e9857e1e973a71cc7ab0099740 Mon Sep 17 00:00:00 2001 From: Gordon Ross Date: Wed, 25 Feb 2026 17:28:30 -0500 Subject: [PATCH 3/3] review 2 -- just use NAME_MAX --- .../pal_x509.c | 23 +++++++++---------- 1 file changed, 11 insertions(+), 12 deletions(-) diff --git a/src/native/libs/System.Security.Cryptography.Native/pal_x509.c b/src/native/libs/System.Security.Cryptography.Native/pal_x509.c index 7cd3c13f5897df..d3da1b8e582be5 100644 --- a/src/native/libs/System.Security.Cryptography.Native/pal_x509.c +++ b/src/native/libs/System.Security.Cryptography.Native/pal_x509.c @@ -11,6 +11,10 @@ #include #include +#ifndef NAME_MAX +#error "NAME_MAX is not defined" +#endif + c_static_assert(PAL_X509_V_OK == X509_V_OK); c_static_assert(PAL_X509_V_ERR_UNABLE_TO_GET_ISSUER_CERT == X509_V_ERR_UNABLE_TO_GET_ISSUER_CERT); c_static_assert(PAL_X509_V_ERR_UNABLE_TO_GET_CRL == X509_V_ERR_UNABLE_TO_GET_CRL); @@ -435,14 +439,6 @@ X509* CryptoNative_X509UpRef(X509* x509) return x509; } -// On some platforms (like illumos), d_name is declared as char[1], so sizeof(d_name) doesn't give -// the actual maximum length. Use NAME_MAX or MAXNAMLEN instead. -#ifdef NAME_MAX -static size_t maxNameLen = NAME_MAX; -#else -static size_t maxNameLen = 255; // Reasonable default -#endif - static DIR* OpenUserStore(const char* storePath, char** pathTmp, size_t* pathTmpSize, char** nextFileWrite) { DIR* trustDir = opendir(storePath); @@ -456,9 +452,12 @@ static DIR* OpenUserStore(const char* storePath, char** pathTmp, size_t* pathTmp size_t storePathLen = strlen(storePath); - // Allocate enough space for the store path, a '/', the maximum filename length, and a null terminator - - size_t allocSize = storePathLen + maxNameLen + 2; // +2 for '/' and '\0' + // d_name is a fixed length char[], not a char*. + // The traditional declaration (eg. SunOS) is d_name[1] + // so we can't assume sizeof(ent->d_name) will work, + // so just use NAME_MAX which is the POSIX way. + // Leave one byte for '\0' and one for '/' + size_t allocSize = storePathLen + NAME_MAX + 2; char* tmp = (char*)calloc(allocSize, sizeof(char)); if (!tmp) { @@ -488,7 +487,7 @@ static X509* ReadNextPublicCert(DIR* dir, X509Stack* tmpStack, char* pathTmp, si while ((next = readdir(dir)) != NULL) { - size_t len = strnlen(next->d_name, maxNameLen); + size_t len = strnlen(next->d_name, NAME_MAX); if (len > 4 && 0 == strncasecmp(".pfx", next->d_name + len - 4, 4)) {