diff --git a/Lib/test/test_socket.py b/Lib/test/test_socket.py index 02c99b402da..e0912d85304 100644 --- a/Lib/test/test_socket.py +++ b/Lib/test/test_socket.py @@ -637,6 +637,11 @@ class GeneralModuleTests(unittest.TestCase): flags=socket.AI_PASSIVE) self.assertEqual(a, b) + def test_idna(self): + # these should all be successful + socket.gethostbyname('испытание.python.org') + socket.gethostbyname_ex('испытание.python.org') + socket.getaddrinfo('испытание.python.org',0) @unittest.skipUnless(thread, 'Threading required for this test.') class BasicTCPTest(SocketConnectedTest): diff --git a/Misc/NEWS b/Misc/NEWS index 790143daea2..c74c2379d7e 100644 --- a/Misc/NEWS +++ b/Misc/NEWS @@ -66,6 +66,8 @@ Core and Builtins Extensions ---------- +- Issue #1027206: Support IDNA in gethostbyname, gethostbyname_ex and getaddrinfo. + - Issue #9214: Set operations on a KeysView or ItemsView in collections now correctly return a set. (Patch by Eli Bendersky.) diff --git a/Modules/socketmodule.c b/Modules/socketmodule.c index c0c9c84dc7f..709c85e213e 100644 --- a/Modules/socketmodule.c +++ b/Modules/socketmodule.c @@ -3000,12 +3000,16 @@ socket_gethostbyname(PyObject *self, PyObject *args) { char *name; sock_addr_t addrbuf; + PyObject *ret = NULL; - if (!PyArg_ParseTuple(args, "s:gethostbyname", &name)) + if (!PyArg_ParseTuple(args, "et:gethostbyname", "idna", &name)) return NULL; if (setipaddr(name, SAS2SA(&addrbuf), sizeof(addrbuf), AF_INET) < 0) - return NULL; - return makeipaddr(SAS2SA(&addrbuf), sizeof(struct sockaddr_in)); + goto finally; + ret = makeipaddr(SAS2SA(&addrbuf), sizeof(struct sockaddr_in)); +finally: + PyMem_Free(name); + return ret; } PyDoc_STRVAR(gethostbyname_doc, @@ -3156,7 +3160,7 @@ socket_gethostbyname_ex(PyObject *self, PyObject *args) struct sockaddr_in addr; #endif struct sockaddr *sa; - PyObject *ret; + PyObject *ret = NULL; #ifdef HAVE_GETHOSTBYNAME_R struct hostent hp_allocated; #ifdef HAVE_GETHOSTBYNAME_R_3_ARG @@ -3171,10 +3175,10 @@ socket_gethostbyname_ex(PyObject *self, PyObject *args) #endif #endif /* HAVE_GETHOSTBYNAME_R */ - if (!PyArg_ParseTuple(args, "s:gethostbyname_ex", &name)) + if (!PyArg_ParseTuple(args, "et:gethostbyname_ex", "idna", &name)) return NULL; if (setipaddr(name, (struct sockaddr *)&addr, sizeof(addr), AF_INET) < 0) - return NULL; + goto finally; Py_BEGIN_ALLOW_THREADS #ifdef HAVE_GETHOSTBYNAME_R #if defined(HAVE_GETHOSTBYNAME_R_6_ARG) @@ -3204,6 +3208,8 @@ socket_gethostbyname_ex(PyObject *self, PyObject *args) #ifdef USE_GETHOSTBYNAME_LOCK PyThread_release_lock(netdb_lock); #endif +finally: + PyMem_Free(name); return ret; } @@ -3228,7 +3234,7 @@ socket_gethostbyaddr(PyObject *self, PyObject *args) struct sockaddr *sa = (struct sockaddr *)&addr; char *ip_num; struct hostent *h; - PyObject *ret; + PyObject *ret = NULL; #ifdef HAVE_GETHOSTBYNAME_R struct hostent hp_allocated; #ifdef HAVE_GETHOSTBYNAME_R_3_ARG @@ -3250,11 +3256,11 @@ socket_gethostbyaddr(PyObject *self, PyObject *args) int al; int af; - if (!PyArg_ParseTuple(args, "s:gethostbyaddr", &ip_num)) + if (!PyArg_ParseTuple(args, "et:gethostbyaddr", "idna", &ip_num)) return NULL; af = AF_UNSPEC; if (setipaddr(ip_num, sa, sizeof(addr), af) < 0) - return NULL; + goto finally; af = sa->sa_family; ap = NULL; al = 0; @@ -3271,7 +3277,7 @@ socket_gethostbyaddr(PyObject *self, PyObject *args) #endif default: PyErr_SetString(socket_error, "unsupported address family"); - return NULL; + goto finally; } Py_BEGIN_ALLOW_THREADS #ifdef HAVE_GETHOSTBYNAME_R @@ -3298,6 +3304,8 @@ socket_gethostbyaddr(PyObject *self, PyObject *args) #ifdef USE_GETHOSTBYNAME_LOCK PyThread_release_lock(netdb_lock); #endif +finally: + PyMem_Free(ip_num); return ret; }