Edit report at https://bugs.php.net/bug.php?id=65137&edit=1
ID: 65137
Updated by: ab@php.net
Reported by: boen dot robot at gmail dot com
Summary: stream_select misleads when TLS socket is used
-Status: Open
+Status: Feedback
Type: Bug
Package: Streams related
Operating System: Windows Server 2008 R2
PHP Version: 5.5.0
Block user comment: N
Private report: N
New Comment:
Are you using x64 bins? There was a fix related to another bug, but the exact place you've
pointed to was touched
http://git.php.net/?p=php-src.git;a=commitdiff;h=da62fd5ed824bafc4dc3e90278c3d57d8e74cbe1
That's most likely a fix on win64, not sure if it'll affect a 32 bit builds in your case.
Anyway, I'd say it makes sense you to test again with a snap from here http://windows.php.net/downloads/snaps/php-5.5/
(please pick the latest). With those snaps and your snippet I get "stream_select() returned
with errors", but also a lot of warnings with display_errors=1. Used some public sites like
SSL'd google, etc.
Thanks.
Previous Comments:
------------------------------------------------------------------------
[2013-06-26 23:59:08] boen dot robot at gmail dot com
On a quick inspection of the relevant source (and I must note I know nothing about PHP's
internals, nor have I compiled PHP, so take this with a grain of salt), this seems to be the
problematic part:
https://github.com/php/php-src/blob/642721b38a9c5ebf336c81027c0dafd6f9246bd6/ext/openssl/xp_ssl.c#L814
For some reason, when doing a cast for stream_select(), the actual socket is returned directly, as
opposed to this happening after an "sslsock->ssl_active" check, like the other casts,
which I'm guessing is causing the gap between what stream_select() says, and what fread() does.
What's the reason for it being that way anyway?
------------------------------------------------------------------------
[2013-06-26 19:01:21] boen dot robot at gmail dot com
Description:
------------
When stream_select() is called on a socket stream created by stream_socket_client() which uses TLS
(with ADH), it seems to report too early. That is, it would report that that the stream can be read,
but then when you try to read it, it would block, and potentially fail.
The exact same code, if called without encryption, would always work just fine. Also, if right
before receiving, the script is made to sleep for a while (in my case, about 100 miliseconds did the
trick), the script is also fine.
Sample code is hard to give, as this occurs only when the server sends large enough data at once
over the encrypted connection, and I seem to be unable to mock a TLS+ADH server with PHP (which is a
separate issue that, at this point, could be just me being stupid).
I *think* the issue might be that stream_select() reports on the underlying socket (i.e. the data
being received before decryption), rather than the *readable data* from the socket, while fread()
blocks until there's at least 1 byte of readable data to be read. But this shouldn't be so
IMHO.
Note that this occurs not just with PHP 5.5.0, but also the latest releases of 5.4.16 and 5.3.26,
and at least as early as 5.3.8.
Test script:
---------------
NOTE: This script is an "approximation" so to speak, in that it demonstrates the exact
settings for the client where this occurs, but due to the lack of a mock server, it's not
confirmed to always fail.
<?php
$socket = stream_socket_client(
'tls://example.com:8729',
$errno,
$errstr,
2,
STREAM_CLIENT_CONNECT,
stream_context_create(
array('ssl' => array('ciphers' => 'ADH'))
)
);
fwrite($socket, chr(6) . '/login' . chr(0));
$r = array($socket);
$w = $e = null;
if (1 === stream_select($r, $w, $e, null)) {
echo fread($socket, 1);
} else {
echo 'stream_select() returned with errors';
}
Expected result:
----------------
stream_select() should only report the encrypted socket as readable if there's at least 1 byte
of readable data in the buffer that can be read by fread().
Actual result:
--------------
stream_select() reports the encrypted socket as readable, but fread() blocks, and may even time out.
------------------------------------------------------------------------
--
Edit this bug report at https://bugs.php.net/bug.php?id=65137&edit=1