29e1e8
From 0be99f8799e90eaed4e8eeb7d5be7de81dd71360 Mon Sep 17 00:00:00 2001
29e1e8
From: =?UTF-8?q?Petr=20P=C3=ADsa=C5=99?= <ppisar@redhat.com>
29e1e8
Date: Thu, 11 Apr 2019 18:17:16 +0200
29e1e8
Subject: [PATCH] inet_aton: Use getaddrinfo() if possible
29e1e8
MIME-Version: 1.0
29e1e8
Content-Type: text/plain; charset=UTF-8
29e1e8
Content-Transfer-Encoding: 8bit
29e1e8
29e1e8
Socket::inet_aton() used gethostbyname() to process arguments that are
29e1e8
not an IP addres. However, gethostbyname() is not thread-safe and when
29e1e8
called from multiple threads a bogus value can be returned.
29e1e8
29e1e8
This patch does add any new test because a basic inet_aton() usage is
29e1e8
already covered and because reproducing the thread failure would
29e1e8
require flodding DNS servers with thousounds of request.
29e1e8
29e1e8
<https://rt.perl.org/Public/Bug/Display.html?id=97860>
29e1e8
<https://bugzilla.redhat.com/show_bug.cgi?id=1693293>
29e1e8
29e1e8
Signed-off-by: Petr Písař <ppisar@redhat.com>
29e1e8
---
29e1e8
 Socket.xs | 16 +++++++++++++++-
29e1e8
 1 file changed, 15 insertions(+), 1 deletion(-)
29e1e8
29e1e8
diff --git a/Socket.xs b/Socket.xs
29e1e8
index e46c93e..65244dd 100644
29e1e8
--- a/Socket.xs
29e1e8
+++ b/Socket.xs
29e1e8
@@ -764,19 +764,33 @@ inet_aton(host)
29e1e8
 	char *	host
29e1e8
 	CODE:
29e1e8
 	{
29e1e8
+#ifdef HAS_GETADDRINFO
29e1e8
+	struct addrinfo *res;
29e1e8
+	struct addrinfo hints = {0,};
29e1e8
+	hints.ai_family = AF_INET;
29e1e8
+	if (!getaddrinfo(host, NULL, &hints, &res)) {
29e1e8
+	    ST(0) = sv_2mortal(newSVpvn(
29e1e8
+		(char *)&(((struct sockaddr_in *)res->ai_addr)->sin_addr.s_addr),
29e1e8
+		4
29e1e8
+	));
29e1e8
+	freeaddrinfo(res);
29e1e8
+	XSRETURN(1);
29e1e8
+    }
29e1e8
+#else
29e1e8
 	struct in_addr ip_address;
29e1e8
 	struct hostent * phe;
29e1e8
-
29e1e8
 	if ((*host != '\0') && inet_aton(host, &ip_address)) {
29e1e8
 		ST(0) = sv_2mortal(newSVpvn((char *)&ip_address, sizeof(ip_address)));
29e1e8
 		XSRETURN(1);
29e1e8
 	}
29e1e8
 #ifdef HAS_GETHOSTBYNAME
29e1e8
+	/* gethostbyname is not thread-safe */
29e1e8
 	phe = gethostbyname(host);
29e1e8
 	if (phe && phe->h_addrtype == AF_INET && phe->h_length == 4) {
29e1e8
 		ST(0) = sv_2mortal(newSVpvn((char *)phe->h_addr, phe->h_length));
29e1e8
 		XSRETURN(1);
29e1e8
 	}
29e1e8
+#endif
29e1e8
 #endif
29e1e8
 	XSRETURN_UNDEF;
29e1e8
 	}
29e1e8
-- 
29e1e8
2.20.1
29e1e8