Bug #78231 [Opn->Ver]: Segmentation fault upon stream_socket_accept of exported socket-to-stream
| From: | nikic@php.net | Date: | Wed, 03 Jul 2019 09:58:56 +0000 |
| Subject: | Bug #78231 [Opn->Ver]: Segmentation fault upon stream_socket_accept of exported socket-to-stream | ||
| References: | 1 | Groups: | php.bugs |
| Request: | Send a blank email to php-bugs+get-221613@lists.php.net to get a copy of this message | ||
Edit report at https://bugs.php.net/bug.php?id=78231&edit=1
ID: 78231
Updated by: nikic@php.net
Reported by: asmqb7 at gmail dot com
Summary: Segmentation fault upon stream_socket_accept of
exported socket-to-stream
-Status: Open
+Status: Verified
Type: Bug
Package: Sockets related
Operating System: Linux
-PHP Version: 7.3.6
+PHP Version: 7.2.20, 7.3.6
Block user comment: N
Private report: N
New Comment:
Confirming segfault, also on 7.2.
Previous Comments:
------------------------------------------------------------------------
[2019-06-29 06:05:40] asmqb7 at gmail dot com
Description:
------------
Due to lack of documentation about the fact that SO_REUSEADDR is unconditionally set when
stream_socket_server() is used, I thought I would need to use the socket_* functions to set the
option on a stream I'd already created.
I figured I could then export the newly-bound socket to a stream, and proceed from there without
needing to use any other socket_* functions, which I try to avoid using as I've been bitten by
the sockets extension in the past (other bugs etc).
Well, I'm not quite sure what I broke this time, but the attached test script segfaults on my
system with 100% consistency. I suspect the code path that handles "stream bound by the sockets
library, exported, then selected on by the streams subsystem" is probably un[der?]implemented.
It's not visible yet, but I added some info to the notes section at http://php.net/socket_set_option, which is what shows
up most prominently when googling SO_REUSEADDR in the context of PHP.
Test script:
---------------
<?php
$port = 55555;
$socket = socket_create(AF_INET, SOCK_STREAM, SOL_TCP);
print '$socket: '; var_dump($socket);
print 'socket_bind(): ';
var_dump(socket_bind($socket, '127.0.0.1', $port));
$listening_fd = socket_export_stream($socket);
print 'socket_export_stream(): ';
var_dump($listening_fd);
for (;;) {
$read = $write = $except = [];
$read[] = $listening_fd;
stream_select($read, $write, $except, null);
foreach ($read as $fd) {
switch ($fd) {
case $listening_fd:
print "stream_socket_accept() on: "; var_dump($fd);
$new_fd = stream_socket_accept($fd);
}
}
}
Expected result:
----------------
For a stream exported from a socket to behave identically to a stream created by the streams
functionality, and particularly for untested codepaths to not cause runtime segfaults.
Actual result:
--------------
$socket: resource(4) of type (Socket)
socket_bind(): bool(true)
socket_export_stream(): resource(5) of type (stream)
stream_socket_accept() on: resource(5) of type (stream)
Program received signal SIGSEGV, Segmentation fault.
0x00005555558ce3b6 in php_stream_context_get_option ()
(gdb) bt
#0 0x00005555558ce3b6 in php_stream_context_get_option ()
#1 0x00005555556df1bc in ?? ()
#2 0x00005555558cc72d in _php_stream_set_option ()
#3 0x00005555558d6560 in php_stream_xport_accept ()
#4 0x0000555555884378 in ?? ()
#5 0x0000555555994a85 in execute_ex ()
#6 0x000055555599aaf6 in zend_execute ()
#7 0x00005555559136aa in zend_execute_scripts ()
#8 0x00005555558b35c9 in php_execute_script ()
#9 0x000055555599d0f6 in ?? ()
#10 0x000055555569e0a7 in ?? ()
#11 0x00007ffff72abce3 in __libc_start_
------------------------------------------------------------------------
--
Edit this bug report at https://bugs.php.net/bug.php?id=78231&edit=1