diff --git a/ext/standard/tests/streams/bug60106.phpt b/ext/standard/tests/streams/bug60106-001.phpt similarity index 78% rename from ext/standard/tests/streams/bug60106.phpt rename to ext/standard/tests/streams/bug60106-001.phpt index 1b36af1a3d9..82c0d94a734 100644 --- a/ext/standard/tests/streams/bug60106.phpt +++ b/ext/standard/tests/streams/bug60106-001.phpt @@ -1,5 +1,5 @@ --TEST-- -Bug#60106 (stream_socket_server silently truncates long unix socket paths) +Bug #60106 (stream_socket_server silently truncates long unix socket paths) --SKIPIF-- +--FILE-- + +--EXPECTF-- +stream_socket_server(): socket path exceeded the maximum allowed length of %d bytes and was truncated +stream_socket_server(): socket path exceeded the maximum allowed length of %d bytes and was truncated +Allowed length is now one more: yes diff --git a/main/streams/xp_socket.c b/main/streams/xp_socket.c index 2c114cd66a9..3d035de6edb 100644 --- a/main/streams/xp_socket.c +++ b/main/streams/xp_socket.c @@ -590,18 +590,23 @@ static inline int parse_unix_address(php_stream_xport_param *xparam, struct sock memset(unix_addr, 0, sizeof(*unix_addr)); unix_addr->sun_family = AF_UNIX; + /* Abstract namespace does not need to be NUL-terminated, while path-based + * sockets should be. */ + bool is_abstract_ns = xparam->inputs.namelen > 0 && xparam->inputs.name[0] == '\0'; + unsigned long max_length = is_abstract_ns ? sizeof(unix_addr->sun_path) : sizeof(unix_addr->sun_path) - 1; + /* we need to be binary safe on systems that support an abstract * namespace */ - if (xparam->inputs.namelen >= sizeof(unix_addr->sun_path)) { + if (xparam->inputs.namelen > max_length) { /* On linux, when the path begins with a NUL byte we are * referring to an abstract namespace. In theory we should * allow an extra byte below, since we don't need the NULL. * BUT, to get into this branch of code, the name is too long, * so we don't care. */ - xparam->inputs.namelen = sizeof(unix_addr->sun_path) - 1; + xparam->inputs.namelen = max_length; php_error_docref(NULL, E_NOTICE, "socket path exceeded the maximum allowed length of %lu bytes " - "and was truncated", (unsigned long)sizeof(unix_addr->sun_path)); + "and was truncated", max_length); } memcpy(unix_addr->sun_path, xparam->inputs.name, xparam->inputs.namelen);