Commit 4b7108ac0f for strongswan.org

commit 4b7108ac0f84fbf40da2b510eb6333afa2a54240
Author: Tobias Brunner <tobias@strongswan.org>
Date:   Mon Jun 8 09:19:42 2026 +0200

    message: Avoid memory leak if string buffer for message is too small

    This leaked 40 or 80 bytes per parsed message for the enumerators that
    were not destroyed.  While triggering an OOM condition will require quite
    a lot of messages and the DoS protection also helps avoiding that this
    is triggered quickly, it all depends on the memory constraints of the
    system and the time available to the attacker.  Also, if IKEv1 is allowed,
    it could get quicker as the lack of message IDs doesn't allow dismissing
    unexpected messages before parsing them.

    Fixes: 092958c89d52 ("fixed payload debug message")
    Fixes: 6a4a47511f75 ("Show contents of the CP payload in message_t stringification")
    Fixes: CVE-2026-78127

diff --git a/src/libcharon/encoding/message.c b/src/libcharon/encoding/message.c
index 8da9a1d71e..a4bf9cb26b 100644
--- a/src/libcharon/encoding/message.c
+++ b/src/libcharon/encoding/message.c
@@ -1398,7 +1398,7 @@ static char* get_string(private_message_t *this, char *buf, int len)
 						   payload->get_type(payload));
 		if (written >= len || written < 0)
 		{
-			return buf;
+			goto err;
 		}
 		pos += written;
 		len -= written;
@@ -1424,7 +1424,7 @@ static char* get_string(private_message_t *this, char *buf, int len)
 			}
 			if (written >= len || written < 0)
 			{
-				return buf;
+				goto err;
 			}
 			pos += written;
 			len -= written;
@@ -1454,7 +1454,7 @@ static char* get_string(private_message_t *this, char *buf, int len)
 							   eap->get_code(eap), method);
 			if (written >= len || written < 0)
 			{
-				return buf;
+				goto err;
 			}
 			pos += written;
 			len -= written;
@@ -1495,7 +1495,8 @@ static char* get_string(private_message_t *this, char *buf, int len)
 								   attribute->get_type(attribute));
 				if (written >= len || written < 0)
 				{
-					return buf;
+					attributes->destroy(attributes);
+					goto err;
 				}
 				pos += written;
 				len -= written;
@@ -1507,7 +1508,7 @@ static char* get_string(private_message_t *this, char *buf, int len)
 				written = snprintf(pos, len, ")");
 				if (written >= len || written < 0)
 				{
-					return buf;
+					goto err;
 				}
 				pos += written;
 				len -= written;
@@ -1529,7 +1530,7 @@ static char* get_string(private_message_t *this, char *buf, int len)
 			}
 			if (written >= len || written < 0)
 			{
-				return buf;
+				goto err;
 			}
 			pos += written;
 			len -= written;
@@ -1544,7 +1545,7 @@ static char* get_string(private_message_t *this, char *buf, int len)
 							   frag->get_total_fragments(frag));
 			if (written >= len || written < 0)
 			{
-				return buf;
+				goto err;
 			}
 			pos += written;
 			len -= written;
@@ -1557,16 +1558,16 @@ static char* get_string(private_message_t *this, char *buf, int len)
 			written = snprintf(pos, len, "(%d)", unknown->get_type(unknown));
 			if (written >= len || written < 0)
 			{
-				return buf;
+				goto err;
 			}
 			pos += written;
 			len -= written;
 		}
 	}
-	enumerator->destroy(enumerator);
-
-	/* remove last space */
 	snprintf(pos, len, " ]");
+
+err:
+	enumerator->destroy(enumerator);
 	return buf;
 }
 #endif