Handle AF_UNIX addresses according to PEP 383. socket.connect(), etc., previously accepted read-only buffers, so in order to accept bytearray pathnames, they now accept any PyBUF_SIMPLE in addition to surrogateescape-encoded strings. diff --git a/Modules/socketmodule.c b/Modules/socketmodule.c --- a/Modules/socketmodule.c +++ b/Modules/socketmodule.c @@ -972,8 +972,12 @@ makesockaddr(int sockfd, struct sockaddr else #endif /* linux */ { - /* regular NULL-terminated string */ - return PyUnicode_FromString(a->sun_path); + /* XXX: this is broken - sun_path is not always + null-terminated. See issue #8372. */ + return PyUnicode_Decode(a->sun_path, + strlen(a->sun_path), + Py_FileSystemDefaultEncoding, + "surrogateescape"); } } #endif /* AF_UNIX */ @@ -1144,40 +1148,58 @@ getsockaddrarg(PySocketSockObject *s, Py case AF_UNIX: { struct sockaddr_un* addr; - char *path; - int len; - if (!PyArg_Parse(args, "s#", &path, &len)) - return 0; + Py_buffer view; + int retval = 0; + + /* PEP 383. Not using PyUnicode_FSConverter since we + need to allow embedded nulls on Linux, and previous + versions accepted read-only buffers here. */ + if (PyUnicode_Check(args)) { + args = PyUnicode_AsEncodedString( + args, Py_FileSystemDefaultEncoding, + "surrogateescape"); + if (args == NULL) + return 0; + } + else + Py_INCREF(args); + if (!PyArg_Parse(args, "y*", &view)) + goto unix_out; addr = (struct sockaddr_un*)addr_ret; #ifdef linux - if (len > 0 && path[0] == 0) { + if (view.len > 0 && ((char *)view.buf)[0] == 0) { /* Linux abstract namespace extension */ - if (len > sizeof addr->sun_path) { + if (view.len > sizeof(addr->sun_path)) { PyErr_SetString(socket_error, "AF_UNIX path too long"); - return 0; + goto unix_releasebuf; } } else #endif /* linux */ { /* regular NULL-terminated string */ - if (len >= sizeof addr->sun_path) { + if (view.len >= sizeof(addr->sun_path)) { PyErr_SetString(socket_error, "AF_UNIX path too long"); - return 0; + goto unix_releasebuf; } - addr->sun_path[len] = 0; + addr->sun_path[view.len] = 0; } addr->sun_family = s->sock_family; - memcpy(addr->sun_path, path, len); + memcpy(addr->sun_path, view.buf, view.len); #if defined(PYOS_OS2) *len_ret = sizeof(*addr); #else - *len_ret = len + offsetof(struct sockaddr_un, sun_path); -#endif - return 1; + *len_ret = view.len + offsetof(struct sockaddr_un, sun_path); +#endif + retval = 1; + unix_releasebuf: + PyBuffer_Release(&view); + unix_out: + Py_DECREF(args); + return retval; } #endif /* AF_UNIX */