1
0
mirror of https://github.com/wolfSSL/wolfssl.git synced 2026-10-24 04:09:07 +03:00

Store the SNI host name with its object

TLSX_SNI_New() allocated the object and then the host name it points at, so
every server name costs two allocations and two frees. Put the name in a
flexible array at the end of the object instead. A union cannot hold one, so
the single member data union goes and the name is sni->host_name.

The host name is the only SNI type there is, so the switch that picked the
allocation to make becomes an early return for any other type, which is what
the default case did anyway.
This commit is contained in:
Tobias Frauenschlaeger
2026-08-21 22:32:56 +00:00
committed by Tobias Frauenschläger
parent b56c027267
commit 0a23c155de
4 changed files with 31 additions and 50 deletions

View File

@@ -2277,37 +2277,27 @@ int TLSX_ALPN_GetRequest(TLSX* extensions, void** data, word16 *dataSz)
/** Creates a new SNI object. */
static SNI* TLSX_SNI_New(byte type, const void* data, word16 size, void* heap)
{
SNI* sni = (SNI*)XMALLOC(sizeof(SNI), heap, DYNAMIC_TYPE_TLSX);
SNI* sni;
(void)heap;
if (sni) {
sni->type = type;
sni->next = NULL;
if (type != WOLFSSL_SNI_HOST_NAME) /* invalid type */
return NULL;
#ifndef NO_WOLFSSL_SERVER
sni->options = 0;
sni->status = WOLFSSL_SNI_NO_MATCH;
#endif
sni = (SNI*)XMALLOC(sizeof(SNI) + size + 1, heap, DYNAMIC_TYPE_TLSX);
if (sni == NULL)
return NULL;
switch (sni->type) {
case WOLFSSL_SNI_HOST_NAME:
sni->data.host_name = (char*)XMALLOC(size + 1, heap,
DYNAMIC_TYPE_TLSX);
if (sni->data.host_name) {
XSTRNCPY(sni->data.host_name, (const char*)data, size);
sni->data.host_name[size] = '\0';
} else {
XFREE(sni, heap, DYNAMIC_TYPE_TLSX);
sni = NULL;
}
break;
sni->type = type;
sni->next = NULL;
default: /* invalid type */
XFREE(sni, heap, DYNAMIC_TYPE_TLSX);
sni = NULL;
}
}
#ifndef NO_WOLFSSL_SERVER
sni->options = 0;
sni->status = WOLFSSL_SNI_NO_MATCH;
#endif
XSTRNCPY(sni->host_name, (const char*)data, size);
sni->host_name[size] = '\0';
return sni;
}
@@ -2316,12 +2306,6 @@ static SNI* TLSX_SNI_New(byte type, const void* data, word16 size, void* heap)
static void TLSX_SNI_Free(SNI* sni, void* heap)
{
if (sni) {
switch (sni->type) {
case WOLFSSL_SNI_HOST_NAME:
XFREE(sni->data.host_name, heap, DYNAMIC_TYPE_TLSX);
break;
}
XFREE(sni, heap, DYNAMIC_TYPE_TLSX);
}
(void)heap;
@@ -2351,7 +2335,7 @@ WOLFSSL_TEST_VIS word16 TLSX_SNI_GetSize(SNI* list)
switch (sni->type) {
case WOLFSSL_SNI_HOST_NAME:
length += (word32)XSTRLEN((char*)sni->data.host_name);
length += (word32)XSTRLEN((char*)sni->host_name);
break;
}
@@ -2377,12 +2361,12 @@ static word16 TLSX_SNI_Write(SNI* list, byte* output)
switch (sni->type) {
case WOLFSSL_SNI_HOST_NAME:
length = (word16)XSTRLEN((char*)sni->data.host_name);
length = (word16)XSTRLEN((char*)sni->host_name);
c16toa(length, output + offset); /* sni length */
offset += OPAQUE16_LEN;
XMEMCPY(output + offset, sni->data.host_name, length);
XMEMCPY(output + offset, sni->host_name, length);
offset += length;
break;
@@ -2579,7 +2563,7 @@ static int TLSX_SNI_Parse(WOLFSSL* ssl, const byte* input, word16 length,
#endif
{
const char* hostName;
hostName = (sni != NULL) ? sni->data.host_name : NULL;
hostName = (sni != NULL) ? sni->host_name : NULL;
matched = cacheOnly || (hostName != NULL &&
XSTRLEN(hostName) == size &&
XSTRNCMP(hostName, (const char*)input + offset, size) == 0);
@@ -2756,7 +2740,7 @@ word16 TLSX_SNI_GetRequest(TLSX* extensions, byte type, void** data,
switch (sni->type) {
case WOLFSSL_SNI_HOST_NAME:
if (data) {
*data = sni->data.host_name;
*data = sni->host_name;
return (word16)XSTRLEN((char*)*data);
}
}

View File

@@ -2371,17 +2371,12 @@ int test_TLSX_SNI_GetSize_overflow(void)
/* Append many SNI nodes to force overflow in the size calculation */
for (i = 1; EXPECT_SUCCESS() && i < num_sni; i++) {
sni = (SNI*)XMALLOC(sizeof(SNI), NULL, DYNAMIC_TYPE_TLSX);
sni = (SNI*)XMALLOC(sizeof(SNI) + 2, NULL, DYNAMIC_TYPE_TLSX);
ExpectNotNull(sni);
if (sni != NULL) {
XMEMSET(sni, 0, sizeof(SNI));
XMEMSET(sni, 0, sizeof(SNI) + 2);
sni->type = WOLFSSL_SNI_HOST_NAME;
sni->data.host_name = (char*)XMALLOC(2, NULL, DYNAMIC_TYPE_TLSX);
ExpectNotNull(sni->data.host_name);
if (sni->data.host_name != NULL) {
sni->data.host_name[0] = 'a';
sni->data.host_name[1] = '\0';
}
sni->host_name[0] = 'a';
sni->next = head->next;
head->next = sni;
}

View File

@@ -44,9 +44,8 @@
#if !defined(NO_WOLFSSL_CLIENT) && !defined(NO_TLS) && \
defined(HAVE_TLS_EXTENSIONS)
/* TLSX_SNI_Free() is file-static in src/tls.c. A test that detaches an SNI
* list from its extension has to release it the same way: the host name, then
* the node. */
/* TLSX_SNI_Free() is file-static in src/tls.c. Each SNI node is one
* allocation that also holds the host name. */
#ifdef HAVE_SNI
TEST_TLS_MSGTYPE_UNUSED
static void test_tls_msgtype_free_sni(void* p, void* heap)
@@ -56,8 +55,6 @@ static void test_tls_msgtype_free_sni(void* p, void* heap)
while (sni != NULL) {
SNI* next = sni->next;
if (sni->type == WOLFSSL_SNI_HOST_NAME)
XFREE(sni->data.host_name, heap, DYNAMIC_TYPE_TLSX);
XFREE(sni, heap, DYNAMIC_TYPE_TLSX);
sni = next;
}

View File

@@ -3678,12 +3678,17 @@ WOLFSSL_LOCAL int TLSX_Append(TLSX** list, TLSX_Type type,
typedef struct SNI {
byte type; /* SNI Type */
union { char* host_name; } data; /* SNI Data */
struct SNI* next; /* List Behavior */
byte status; /* Matching result */
#ifndef NO_WOLFSSL_SERVER
byte options; /* Behavior options */
#endif
/* Ignore "nonstandard extension used : zero-sized array in struct/union"
* MSVC warning */
#ifdef _MSC_VER
#pragma warning(disable: 4200)
#endif
char host_name[WC_FLEXIBLE_ARRAY_SIZE]; /* SNI Data */
} SNI;
WOLFSSL_LOCAL int TLSX_UseSNI(TLSX** extensions, byte type, const void* data,