File 1271-Verify-family-of-struct-addrinfo-replies.patch of Package erlang

From 1f7154fc5fb2ea1f8b532b79bb8adbcb597f344e Mon Sep 17 00:00:00 2001
From: Raimo Niskanen <raimo@erlang.org>
Date: Tue, 24 Aug 2021 17:20:57 +0200
Subject: [PATCH 1/2] Verify family of struct addrinfo replies

---
 erts/etc/common/inet_gethost.c | 89 +++++++++++++++++++---------------
 1 file changed, 50 insertions(+), 39 deletions(-)

diff --git a/erts/etc/common/inet_gethost.c b/erts/etc/common/inet_gethost.c
index 12012a056e..812f282aaa 100644
--- a/erts/etc/common/inet_gethost.c
+++ b/erts/etc/common/inet_gethost.c
@@ -324,8 +324,9 @@ static size_t build_error_reply(SerialType serial, int errnum,
 				AddrByte **preply,
 				size_t *preply_size);
 #ifdef HAVE_GETADDRINFO
-static size_t build_reply_ai(SerialType serial, int, struct addrinfo *,
-                            AddrByte **preply, size_t *preply_size);
+static size_t build_reply_ai(SerialType serial, int, int,
+                             struct addrinfo *,
+                             AddrByte **preply, size_t *preply_size);
 #endif
 static size_t build_reply(SerialType serial, struct hostent *he,
                          AddrByte **preply, size_t *preply_size);
@@ -1821,7 +1822,7 @@ static int worker_loop(void)
 #endif
 #ifdef HAVE_GETADDRINFO
 	    } else if (ai) {
-		data_size = build_reply_ai(serial, 16, ai,
+		data_size = build_reply_ai(serial, AF_INET6, 16, ai,
 					   &reply, &reply_size);
 		freeaddrinfo(ai);
 #endif
@@ -1836,17 +1837,17 @@ static int worker_loop(void)
 #ifdef HAVE_IN6
 	    case PROTO_IPV6: {
 #ifdef HAVE_GETNAMEINFO
-		struct sockaddr_in6 *sin;
-		socklen_t salen = sizeof(*sin);
+		struct sockaddr_in6 *sin6;
+		socklen_t salen = sizeof(*sin6);
 		
-		sin = ALLOC(salen);
+		sin6 = ALLOC(salen);
 #ifndef NO_SA_LEN
-		sin->sin6_len = salen;
+		sin6->sin6_len = salen;
 #endif
-		sin->sin6_family = AF_INET6;
-		sin->sin6_port = 0;
-		memcpy(&sin->sin6_addr, data, 16);
-		sa = (struct sockaddr *)sin;
+		sin6->sin6_family = AF_INET6;
+		sin6->sin6_port = 0;
+		memcpy(&sin6->sin6_addr, data, 16);
+		sa = (struct sockaddr *)sin6;
 		DEBUGF(5,("Starting getnameinfo(,,%s,16,,,)",
 			  format_address(16, data)));
 		error_num = getnameinfo(sa, salen, name, sizeof(name),
@@ -1916,8 +1917,9 @@ static int worker_loop(void)
 		memset(&res, 0, sizeof(res));
 		res.ai_canonname = name;
 		res.ai_addr = sa;
+                res.ai_family = sa->sa_family;
 		res.ai_next = NULL;
-		data_size = build_reply_ai(serial, 16, &res,
+		data_size = build_reply_ai(serial, AF_INET6, 16, &res,
 					   &reply, &reply_size);
 		free(sa);
 #endif
@@ -2144,7 +2146,8 @@ static size_t build_reply(SerialType serial, struct hostent *he,
 }
 
 #if defined(HAVE_GETADDRINFO) || defined(HAVE_GETNAMEINFO)
-static size_t build_reply_ai(SerialType serial, int addrlen,
+static size_t build_reply_ai(SerialType serial,
+                             int family, int addrlen,
 			     struct addrinfo *res0,
 			     AddrByte **preply, size_t *preply_size)
 {
@@ -2161,14 +2164,16 @@ static size_t build_reply_ai(SerialType serial, int addrlen,
 	4 /* Naddr */ + 4 /* Nnames */;
 
     for (res = res0; res != NULL; res = res->ai_next) {
-	if (res->ai_addr) {
-	    num_addresses++;
-	    need += addrlen;
-	}
-	if (res->ai_canonname) {
-	    num_strings++;
-	    need += strlen(res->ai_canonname) + 1;
-	}
+        if ((res->ai_addr) &&
+            (res->ai_addr->sa_family == family)) {
+            num_addresses++;
+            need += addrlen;
+        }
+        if ((res->ai_canonname) &&
+            (res->ai_family == family)) {
+            num_strings++;
+            need += strlen(res->ai_canonname) + 1;
+        }
     }
 
     if (*preply_size < need) {
@@ -2188,28 +2193,34 @@ static size_t build_reply_ai(SerialType serial, int addrlen,
     *ptr++ = (AddrByte) addrlen; /* 4 or 16 */
     put_int32(ptr, num_addresses);
     ptr += 4;
-    for (res = res0; res != NULL && num_addresses; res = res->ai_next) {
-	if (res->ai_addr == NULL)
-	    continue;
-	if (addrlen == 4)
-	    memcpy(ptr, &((struct sockaddr_in *)res->ai_addr)->sin_addr, addrlen);
+    for (res = res0; res != NULL; res = res->ai_next) {
+        if ((res->ai_addr) &&
+            (res->ai_addr->sa_family == family)) {
+            const void *src;
+            switch (family) {
+            case AF_INET:
+                src = &((struct sockaddr_in *)res->ai_addr)->sin_addr;
+                break;
 #ifdef AF_INET6
-	else if (addrlen == 16)
-	    memcpy(ptr, &((struct sockaddr_in6 *)res->ai_addr)->sin6_addr, addrlen);
+            case AF_INET6:
+                src = &((struct sockaddr_in6 *)res->ai_addr)->sin6_addr;
+                break;
 #endif
-	else
-	    memcpy(ptr, res->ai_addr->sa_data, addrlen);
-	ptr += addrlen;
-	num_addresses--;
+            default:
+                src = res->ai_addr->sa_data;
+            }
+            memcpy(ptr, src, addrlen);
+            ptr += addrlen;
+        }
     }
     put_int32(ptr, num_strings);
     ptr += 4;
-    for (res = res0; res != NULL && num_strings; res = res->ai_next) {
-	if (res->ai_canonname == NULL)
-	    continue;
-	strcpy((char *)ptr, res->ai_canonname);
-	ptr += strlen(res->ai_canonname) + 1;
-	num_strings--;
+    for (res = res0; res != NULL; res = res->ai_next) {
+        if ((res->ai_canonname) &&
+            (res->ai_family == family)) {
+            strcpy((char *)ptr, res->ai_canonname);
+            ptr += strlen(res->ai_canonname) + 1;
+        }
     }
     return need;
 }
-- 
2.31.1

openSUSE Build Service is sponsored by