php.net |  support |  documentation |  report a bug |  advanced search |  search howto |  statistics |  random bug |  login
Bug #80723 Different sockets compare as equal (regression in 8.0)
Submitted: 2021-02-08 02:44 UTC Modified: 2021-02-16 11:36 UTC
From: bugs-a17 at moonlit-rail dot com Assigned: nikic (profile)
Status: Closed Package: Sockets related
PHP Version: 8.0.2 OS: Linux
Private report: No CVE-ID: None
 [2021-02-08 02:44 UTC] bugs-a17 at moonlit-rail dot com
Description:
------------
In PHP 8.0, two different sockets compare as equal.
This is a regression versus PHP 7.x.

I use PHP for writing internet servers, and upgrading to 8.0 sees most of them failing.  Simple constructs such as, $socknum = array_search($sock, $sockets)
no longer function as they intuitively ought to.

As an aside, it used to be convenient to do, $array[(int)$socket] = $socket;
But in 8.0, (int) $socket bombs, and var_export($socket, true) returns the same value regardless of what's in the socket.

Test script:
---------------
#!/usr/bin/php
<?php

$socket_1 = socket_create(AF_INET, SOCK_STREAM, SOL_TCP);
$socket_2 = socket_create(AF_INET, SOCK_STREAM, SOL_TCP);
$vector   = array(1 => $socket_1,
                  2 => $socket_2);
$IDX_1    = array_search($socket_1, $vector);
$IDX_2    = array_search($socket_2, $vector);
$V        = substr(PHP_VERSION, 0, 3);

echo "In PHP {$V}:\n".
     "\tSocket 1 was found at array index {$IDX_1}, and\n".
     "\tSocket 2 was found at array index {$IDX_2}.\n";

socket_close($socket_1);
socket_close($socket_2);
?>

Expected result:
----------------
~$ /tmp/socket-compare-test.php 
In PHP 7.3:
        Socket 1 was found at array index 1, and
        Socket 2 was found at array index 2.


Actual result:
--------------
~$ /tmp/socket-compare-test.php 
In PHP 8.0:
        Socket 1 was found at array index 1, and
        Socket 2 was found at array index 1.


Patches

Add a Patch

Pull Requests

Add a Pull Request

History

AllCommentsChangesGit/SVN commitsRelated reports
 [2021-02-08 02:57 UTC] danack@php.net
That probably needs to be investigated, but you may be able to use WeakMaps as a better holder for things like this: https://wiki.php.net/rfc/weak_maps

which might need to be documented...
 [2021-02-08 06:24 UTC] bugs-a17 at moonlit-rail dot com
Thanks for the note about the weak-maps, looks quite useful for many of my use cases.

One workaround for this bug is to use === rather than == in the comparison.

As the sockets now create a Socket class, and each instance appears empty, that might explain why <empty> == <empty> returns true; clearly, the Socket object returned by create_socket() should be populated with socket information (or at least a pointer to a resource) to permit the comparison to have something to work with.
 [2021-02-16 11:26 UTC] nikic@php.net
-Assigned To: +Assigned To: nikic
 [2021-02-16 11:34 UTC] nikic@php.net
Automatic comment on behalf of nikita.ppv@gmail.com
Revision: http://git.php.net/?p=php-src.git;a=commit;h=cb9785add1bc8031531c2870c267e6a72efae6af
Log: Fixed bug #80723
 [2021-02-16 11:34 UTC] nikic@php.net
-Status: Assigned +Status: Closed
 [2021-02-16 11:36 UTC] nikic@php.net
The replacement for (int)$socket is spl_object_id($socket). Though we might want to add an overload for sockets in particular, as we did for curl handles.
 
PHP Copyright © 2001-2021 The PHP Group
All rights reserved.
Last updated: Thu Apr 22 03:01:25 2021 UTC