PEAR is archived and read-only

This mirror preserves historical PEAR package releases and metadata so existing references remain available.

Home » Networking » Net_Socket » Bug #5807

(patch) select is broken when out-of-band data present

Details

Submitted2005-10-28 10:17 UTC
Fromalasdair at emarketeers dot com
Assignedchagenbu
StatusClosed
PackageNet_Socket
PHP VersionIrrelevant
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.