Edit report at https://bugs.php.net/bug.php?id=68853&edit=1
ID: 68853
Comment by: boen dot robot at gmail dot com
Reported by: boen dot robot at gmail dot com
Summary: stream_select on a TLS stream does not report last
chunk as readable
Status: Assigned
Type: Bug
Package: OpenSSL related
Operating System: Windows 2008 R2
PHP Version: 5.6.4
Assigned To: rdlowrey
Block user comment: N
Private report: N
New Comment:
I can confirm that the latest 5.6.8 snapshot fixes this issue.
Thank you.
Previous Comments:
------------------------------------------------------------------------
[2015-03-06 17:35:40] rdlowrey@php.net
Related To: Bug #65137
------------------------------------------------------------------------
[2015-03-06 01:02:51] rdlowrey@php.net
I have cherry-picked @DaveRandom's original SSL_pending() solution back into 5.6 and master.
I'm fairly certain this commit solves the problem fully. It was unfortunately reverted due to
its close proximity to some other buggy shenanigans.
This change will *not* appear in the forthcoming 5.6.7 release so that we have time to test, get
feedback and verify that it works everywhere. If you're interested in this bug's
resolution please build the current PHP-5.6 or master branch to verify that the issue is resolved.
------------------------------------------------------------------------
[2015-01-18 15:35:12] boen dot robot at gmail dot com
Description:
------------
If one end (say, client) sends more than one chunk of data (8192 bytes) at once, the last chunk
(8192 or fewer remaining bytes) is not detected as readable by the other end (say, server) with
stream_select() on the connection.
Issue occurs on both ends if they do reading, so whether it's server receiving client data or
client receiving server data - the same thing happens.
This issue does not occur on a plain (non-encrypted) TCP stream. Only on encrypted streams.
This is sort of related to #65137 in that it is apparently caused by stream_select() reporting the
underlying TCP stream, rather than the TLS stream. By the time one calls stream_select() on the last
chunk, the last chunk has already been read from the TCP layer, and is ready to be read, but
there's no way to find that out from PHP userland. Not even stream_get_meta_data() helps - it
reports 0 unread bytes after the last successful fread().
Test script:
---------------
Here's an echo client/server duo demonstrating the issue.
https://gist.github.com/boenrobot/f636eba79043f7303fb4
The server can be ran with the port as an argument, and an optional second argument with the
protocol (tcp or tls; defaults to tcp). The client can be ran with the ip as a first argument, port
as second, and optional port as third (again tcp or tls; defaults to tcp).
From the client, you write the number of bytes to be sent to the server, with PHP_EOL appended after
those, after which reading is done until PHP_EOL is found.
(I also have an equivalent Java version, which I used to confirm that issue occurs on both client
and server; You'll notice MakeKeys.php which generates a self signed certificate and exports it
in .p12 format too - that was for the sake of Java)
Expected result:
----------------
Same as with non-encrypted sockets - you write number of bytes, you send that many (plus EOL), and
get that same many back (plus EOL), after which you can ask for more.
Actual result:
--------------
Trying to send f.e. 8191 on Windows (so 8193 bytes with the EOL in there) makes the server receive
only 8192 bytes, and hanging on that last one. Same with any data larger than that, except that
every next 8192 bytes are received, before the last chunk.
------------------------------------------------------------------------
--
Edit this bug report at https://bugs.php.net/bug.php?id=68853&edit=1