How to not make a function safe
This code comes from the actual sources of the last PHP release (ext/sockets/sockets.c). It's probable that this code has been here like, forever:
First, yes, this is for real a static variable in the C module, those guys don't know about either of the const or static keyword.
/* inet_ntop should be used instead of inet_ntoa */ int inet_ntoa_lock = 0;
/* ... */
Then they wrap getpeername:
PHP_FUNCTION(socket_getpeername)
{
/* ... */
if (getpeername(php_sock->bsd_socket, sa, &salen) < 0) {
PHP_SOCKET_ERROR(php_sock, "unable to retrieve peer name", errno);
RETURN_FALSE;
}
so far so good. Or maybe not so good.
switch (sa->sa_family) {
case AF_INET:
sin = (struct sockaddr_in *) sa;
while (inet_ntoa_lock == 1);
inet_ntoa_lock = 1;
Riiiiiight, locks 101, you fail.
addr_string = inet_ntoa(sin->sin_addr);
inet_ntoa_lock = 0;
QUICK ! let's release the lock before we actually use addr_string !
zval_dtor(arg2);
ZVAL_STRING(arg2, addr_string, 1);
/*... */
And you know the best of it ? Of course that code is totally useless since[1]:
$ grep -wc inet_ntoa **/*.[hc]|grep -v :0 ext/sockets/sockets.c:4 ext/standard/basic_functions.c:1 ext/standard/dns.c:2 main/network.c:1 sapi/cgi/fastcgi.c:1 sapi/tux/php_tux.c:1
Those guys are priceless. Especially when you consider the number of 50-liners to implement inet_ntop that lie around.
Notes
[1] update: this grep means that inet_ntoa isn't wrapped in the code at all, and that this "locking" code, in addition to be pitiful, is just worthless
