Skip to content

Commit e0e9eb4

Browse files
committed
Merge branch 'fix-anonymous-socket-at-length-boundary' into PHP-8.2
2 parents f598b58 + ad56ec7 commit e0e9eb4

File tree

3 files changed

+51
-6
lines changed

3 files changed

+51
-6
lines changed

ext/standard/tests/streams/bug60106.phpt renamed to ext/standard/tests/streams/bug60106-001.phpt

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
--TEST--
2-
Bug#60106 (stream_socket_server silently truncates long unix socket paths)
2+
Bug #60106 (stream_socket_server silently truncates long unix socket paths)
33
--SKIPIF--
44
<?php
55
if( substr(PHP_OS, 0, 3) == "WIN" )
@@ -11,9 +11,9 @@ error_reporting(E_ALL | E_NOTICE);
1111
$socket_file = "/tmp/" . str_repeat("a", 512);
1212
function get_truncated_socket_filename($errno, $errmsg, $file, $line) {
1313
global $socket_file;
14-
print_r ($errmsg);
14+
echo $errmsg, "\n";
1515
preg_match("#maximum allowed length of (\d+) bytes#", $errmsg, $matches);
16-
$socket_file = substr($socket_file, 0, intval($matches[1]) - 1);
16+
$socket_file = substr($socket_file, 0, intval($matches[1]));
1717
}
1818
set_error_handler("get_truncated_socket_filename", E_NOTICE);
1919
stream_socket_server("unix://" . $socket_file);
Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,40 @@
1+
--TEST--
2+
Bug #60106 (stream_socket_server with abstract unix socket paths)
3+
--SKIPIF--
4+
<?php
5+
if (PHP_OS != "Linux") die("skip Only for Linux systems");
6+
?>
7+
--FILE--
8+
<?php
9+
error_reporting(E_ALL | E_NOTICE);
10+
11+
/* This figures out the max length for normal sockets */
12+
$socket_file = "/tmp/" . str_repeat("a", 512);
13+
function get_truncated_socket_filename($errno, $errmsg, $file, $line) {
14+
global $socket_file, $max_normal_length;
15+
echo $errmsg, "\n";
16+
preg_match("#maximum allowed length of (\d+) bytes#", $errmsg, $matches);
17+
$max_normal_length = intval($matches[1]);
18+
$socket_file = substr($socket_file, 0, $max_normal_length);
19+
}
20+
set_error_handler("get_truncated_socket_filename", E_NOTICE);
21+
22+
stream_socket_server("unix://" . $socket_file);
23+
unlink($socket_file);
24+
25+
/* No we create an abstract one, prefixed with \0 so this should now work */
26+
$abstract_socket = "\0" . $socket_file;
27+
stream_socket_server("unix://" . $abstract_socket);
28+
29+
$old_max_length = $max_normal_length;
30+
31+
/* And now one longer, which should fail again */
32+
$abstract_socket_long = "\0" . $abstract_socket . 'X';
33+
stream_socket_server("unix://" . $abstract_socket_long);
34+
35+
echo "Allowed length is now one more: ", $max_normal_length == $old_max_length + 1 ? "yes" : "no", "\n";
36+
?>
37+
--EXPECTF--
38+
stream_socket_server(): socket path exceeded the maximum allowed length of %d bytes and was truncated
39+
stream_socket_server(): socket path exceeded the maximum allowed length of %d bytes and was truncated
40+
Allowed length is now one more: yes

main/streams/xp_socket.c

Lines changed: 8 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -564,18 +564,23 @@ static inline int parse_unix_address(php_stream_xport_param *xparam, struct sock
564564
memset(unix_addr, 0, sizeof(*unix_addr));
565565
unix_addr->sun_family = AF_UNIX;
566566

567+
/* Abstract namespace does not need to be NUL-terminated, while path-based
568+
* sockets should be. */
569+
bool is_abstract_ns = xparam->inputs.namelen > 0 && xparam->inputs.name[0] == '\0';
570+
unsigned long max_length = is_abstract_ns ? sizeof(unix_addr->sun_path) : sizeof(unix_addr->sun_path) - 1;
571+
567572
/* we need to be binary safe on systems that support an abstract
568573
* namespace */
569-
if (xparam->inputs.namelen >= sizeof(unix_addr->sun_path)) {
574+
if (xparam->inputs.namelen > max_length) {
570575
/* On linux, when the path begins with a NUL byte we are
571576
* referring to an abstract namespace. In theory we should
572577
* allow an extra byte below, since we don't need the NULL.
573578
* BUT, to get into this branch of code, the name is too long,
574579
* so we don't care. */
575-
xparam->inputs.namelen = sizeof(unix_addr->sun_path) - 1;
580+
xparam->inputs.namelen = max_length;
576581
php_error_docref(NULL, E_NOTICE,
577582
"socket path exceeded the maximum allowed length of %lu bytes "
578-
"and was truncated", (unsigned long)sizeof(unix_addr->sun_path));
583+
"and was truncated", max_length);
579584
}
580585

581586
memcpy(unix_addr->sun_path, xparam->inputs.name, xparam->inputs.namelen);

0 commit comments

Comments
 (0)