Home » Networking » Net_Socket » Bug #5807
(patch) select is broken when out-of-band data present
Details
| Submitted | 2005-10-28 10:17 UTC |
|---|---|
| From | alasdair at emarketeers dot com |
| Assigned | chagenbu |
| Status | Closed |
| Package | Net_Socket |
| PHP Version | Irrelevant |
| Roadmaps | (Not assigned) |
Comments
[2005-10-28 10:17 UTC] alasdair at emarketeers dot com
Description:
------------
Net_Socket/Socket.php has a bug in the select() method, due to the way the NET_SOCKET_* bitmasks have been defined, resulting in out-of-band data events being selected, even when not requested.
At the head of the code, we have:
define('NET_SOCKET_READ', 1);
define('NET_SOCKET_WRITE', 2);
define('NET_SOCKET_ERROR', 3);
Calling $socket->select(NET_SOCKET_READ, 0);
Specifying NET_SOCKET_READ or NET_SOCKET_WRITE implicitly results in NET_SOCKET_ERROR as well.
Test script:
---------------
Test script
-----------
$socket =& new Net_Socket();
$socket->connect('127.0.0.1', '80');
$r = $socket->select(NET_SOCKET_READ, 0, 0);
if ($r & NET_SOCKET_READ) {
$b = $socket->readByte();
}
Patch
-----
define('NET_SOCKET_READ', 1);
define('NET_SOCKET_WRITE', 2);
-define('NET_SOCKET_ERROR', 3);
+define('NET_SOCKET_ERROR', 4);
Arguably NET_SOCKET_ERROR should also be renamed NET_SOCKET_EXCEPT, since it does not represent any error condition on the socket. For backwards compatibility, the old NET_SOCKET_ERROR define could be retained.
Expected result:
----------------
Internally, a call to:
$r = $socket->select(NET_SOCKET_READ, 0, 0);
should result in the implementation calling:
stream_select(array($this->fp), null, null, 0, 0);
Actual result:
--------------
It actually calls:
stream_select(array($this->fp), null, array($this->fp), 0, 0);
The problem being, if out-of-band data arrives on the socket, (but no data is available in the read buffer), the select() method call will return 3 (NET_SOCKET_ERROR), which is equivalent to NET_SOCKET_READ | NET_SOCKET_WRITE.
The 'if' in this code will then succeed, causing an attempt to read a byte from the socket, which is not in fact there:
if ($r & NET_SOCKET_READ) {
$b = $socket->readByte();
}
[2005-11-15 03:48 UTC] chagenbu at php dot net
This bug has been fixed in CVS.
If this was a documentation problem, the fix will appear on pear.php.net by the end of next Sunday (CET).
If this was a problem with the pear.php.net website, the change should be live shortly.
Otherwise, the fix will appear in the package's next release.
Thank you for the report and for helping us make PEAR better.
We'll try to get a new package release out soon.