Decode hostnames strictly as ASCII. diff --git a/Doc/library/socket.rst b/Doc/library/socket.rst --- a/Doc/library/socket.rst +++ b/Doc/library/socket.rst @@ -255,6 +255,8 @@ The module :mod:`socket` exports the fol .. versionchanged:: 3.2 parameters can now be passed as single keyword arguments. + Raises :exc:`UnicodeDecodeError` if any of the returned names + contain non-ASCII byte values. .. function:: getfqdn([name]) @@ -286,6 +288,10 @@ The module :mod:`socket` exports the fol resolution, and :func:`getaddrinfo` should be used instead for IPv4/v6 dual stack support. + .. versionchanged:: 3.2 + Raises :exc:`UnicodeDecodeError` if any of the returned names + contain non-ASCII byte values. + .. function:: gethostname() @@ -300,6 +306,9 @@ The module :mod:`socket` exports the fol Note: :func:`gethostname` doesn't always return the fully qualified domain name; use ``getfqdn()`` (see above). + .. versionchanged:: 3.2 + Raises :exc:`UnicodeDecodeError` if the returned name contains + non-ASCII byte values. .. function:: gethostbyaddr(ip_address) @@ -311,6 +320,10 @@ The module :mod:`socket` exports the fol domain name, use the function :func:`getfqdn`. :func:`gethostbyaddr` supports both IPv4 and IPv6. + .. versionchanged:: 3.2 + Raises :exc:`UnicodeDecodeError` if any of the returned names + contain non-ASCII byte values. + .. function:: getnameinfo(sockaddr, flags) @@ -319,6 +332,10 @@ The module :mod:`socket` exports the fol or numeric address representation in *host*. Similarly, *port* can contain a string port name or a numeric port number. + .. versionchanged:: 3.2 + Raises :exc:`UnicodeDecodeError` if the returned name contains + non-ASCII byte values. + .. function:: getprotobyname(protocolname) diff --git a/Modules/socketmodule.c b/Modules/socketmodule.c --- a/Modules/socketmodule.c +++ b/Modules/socketmodule.c @@ -739,6 +739,15 @@ PyThread_type_lock netdb_lock; #endif +/* Return the string representation for the given hostname. */ + +static PyObject * +decode_hostname(const char *name) +{ + return PyUnicode_DecodeASCII(name, strlen(name), "strict"); +} + + /* Convert a string specifying a host name or one of a few symbolic names to a numeric IP address. This usually calls gethostbyname() to do the work; the names "" and "" are special. @@ -2983,7 +2992,7 @@ socket_gethostname(PyObject *self, PyObj if (res < 0) return set_error(); buf[sizeof buf - 1] = '\0'; - return PyUnicode_FromString(buf); + return decode_hostname(buf); } PyDoc_STRVAR(gethostname_doc, @@ -3069,7 +3078,7 @@ gethost_common(struct hostent *h, struct if (h->h_aliases) { for (pch = h->h_aliases; *pch != NULL; pch++) { int status; - tmp = PyUnicode_FromString(*pch); + tmp = decode_hostname(*pch); if (tmp == NULL) goto err; @@ -3137,7 +3146,8 @@ gethost_common(struct hostent *h, struct goto err; } - rtn_tuple = Py_BuildValue("sOO", h->h_name, name_list, addr_list); + rtn_tuple = Py_BuildValue("NOO", decode_hostname(h->h_name), + name_list, addr_list); err: Py_XDECREF(name_list); @@ -3909,9 +3919,9 @@ socket_getaddrinfo(PyObject *self, PyObj makesockaddr(-1, res->ai_addr, res->ai_addrlen, protocol); if (addr == NULL) goto err; - single = Py_BuildValue("iiisO", res->ai_family, + single = Py_BuildValue("iiiNO", res->ai_family, res->ai_socktype, res->ai_protocol, - res->ai_canonname ? res->ai_canonname : "", + decode_hostname(res->ai_canonname ? res->ai_canonname : ""), addr); Py_DECREF(addr); if (single == NULL) @@ -4011,7 +4021,7 @@ socket_getnameinfo(PyObject *self, PyObj set_gaierror(error); goto fail; } - ret = Py_BuildValue("ss", hbuf, pbuf); + ret = Py_BuildValue("Ns", decode_hostname(hbuf), pbuf); fail: if (res)