diff -r 84c8127453cf Lib/test/test_socket.py --- a/Lib/test/test_socket.py Sat Oct 06 03:40:10 2012 +0200 +++ b/Lib/test/test_socket.py Sat Oct 13 10:56:09 2012 +0200 @@ -726,6 +726,30 @@ if not fqhn in all_host_names: self.fail("Error testing host resolution mechanisms. (fqdn: %s, all: %s)" % (fqhn, repr(all_host_names))) + def test_gethostbyname(self): + hostnames = { + '0.0.0.0' : '0.0.0.0', + '127.0.0.1' : '127.0.0.1', + ' 10.0.0.1' : None, + '0.1.1.1.' : None, + '4294967306.4294967296.4294967296.1' : None, + 'a1.1.1.1' : None, + '10.1a.1.1' : None, + '10.0.0.1รน' : None, + 'thebestipevah' : None, + } + + for host, expected_host in hostnames.items(): + try: + hostbyname = socket.gethostbyname(host) + except socket.error: + if expected_host: + self.fail('Failed to parse {}. Expected: {}'.format( + repr(host), repr(expected_host))) + else: + self.assertEqual(hostbyname, expected_host) + + @unittest.skipUnless(hasattr(socket, 'sethostname'), "test needs socket.sethostname()") @unittest.skipUnless(hasattr(socket, 'gethostname'), "test needs socket.gethostname()") def test_sethostname(self): diff -r 84c8127453cf Modules/socketmodule.c --- a/Modules/socketmodule.c Sat Oct 06 03:40:10 2012 +0200 +++ b/Modules/socketmodule.c Sat Oct 13 10:56:09 2012 +0200 @@ -799,8 +799,10 @@ { struct addrinfo hints, *res; int error; - int d1, d2, d3, d4; - char ch; + uint32_t ip; + long value; + size_t i; + char *str, *strend; memset((void *) addr_ret, '\0', sizeof(*addr_ret)); if (name[0] == '\0') { @@ -865,20 +867,37 @@ sin->sin_addr.s_addr = INADDR_BROADCAST; return sizeof(sin->sin_addr); } - if (sscanf(name, "%d.%d.%d.%d%c", &d1, &d2, &d3, &d4, &ch) == 4 && - 0 <= d1 && d1 <= 255 && 0 <= d2 && d2 <= 255 && - 0 <= d3 && d3 <= 255 && 0 <= d4 && d4 <= 255) { - struct sockaddr_in *sin; - sin = (struct sockaddr_in *)addr_ret; - sin->sin_addr.s_addr = htonl( - ((long) d1 << 24) | ((long) d2 << 16) | - ((long) d3 << 8) | ((long) d4 << 0)); - sin->sin_family = AF_INET; + /* attempt to parse an ip address if of the form %d.%d.%d.%d */ + str = name; + errno = 0; + value = ip = 0; + if (!isdigit(*str)) + goto not_ip; + for (i = 3; i >= 0; i--) { + value = strtol(str, &strend, 10); + if (errno != 0 || value < 0 || value > 255) { + errno = 0; + goto not_ip; + } + ip |= value << (8 * i); + if (*strend == '.') + str = strend + 1; + else + break; + + } + if (i > 0 || *strend != '\0') + goto not_ip; + struct sockaddr_in *sin; + sin = (struct sockaddr_in *)addr_ret; + sin->sin_addr.s_addr = htonl(ip); + sin->sin_family = AF_INET; #ifdef HAVE_SOCKADDR_SA_LEN - sin->sin_len = sizeof(*sin); -#endif - return 4; - } + sin->sin_len = sizeof(*sin); +#endif + return 4; + +not_ip: memset(&hints, 0, sizeof(hints)); hints.ai_family = af; Py_BEGIN_ALLOW_THREADS @@ -1641,7 +1660,7 @@ return 0; } #endif - + #ifdef PF_SYSTEM case PF_SYSTEM: switch (s->sock_proto) { @@ -1649,10 +1668,10 @@ case SYSPROTO_CONTROL: { struct sockaddr_ctl *addr; - + addr = (struct sockaddr_ctl *)addr_ret; addr->sc_family = AF_SYSTEM; - addr->ss_sysaddr = AF_SYS_CONTROL; + addr->ss_sysaddr = AF_SYS_CONTROL; if (PyUnicode_Check(args)) { struct ctl_info info; @@ -1678,17 +1697,17 @@ "cannot find kernel control with provided name"); return 0; } - + addr->sc_id = info.ctl_id; addr->sc_unit = 0; } else if (!PyArg_ParseTuple(args, "II", &(addr->sc_id), &(addr->sc_unit))) { PyErr_SetString(PyExc_TypeError, "getsockaddrarg: " "expected str or tuple of two ints"); - + return 0; } - + *len_ret = sizeof(*addr); return 1; } @@ -1805,7 +1824,7 @@ return 1; } #endif - + #ifdef PF_SYSTEM case PF_SYSTEM: switch(s->sock_proto) {