|
php.net | support | documentation | report a bug | advanced search | search howto | statistics | random bug | login |
[2009-02-12 09:27 UTC] flobee at gmail dot com
Description:
------------
ip2long seems to be buggy on 64 Bit Solaris:
Tested with: php5.2.2, php5.2.8
Reproduce code:
---------------
64bit Solaris
#php -r "echo 'x:' . ip2long('web.de') .\"\n\";"
// x:4294967295
32bit Solaris
#php -r "echo 'x:' . ip2long('web.de') .\"\n\";"
// x:false
PatchesPull RequestsHistoryAllCommentsChangesGit/SVN commits
|
|||||||||||||||||||||||||||||||||||||
Copyright © 2001-2025 The PHP GroupAll rights reserved. |
Last updated: Mon Oct 27 18:00:01 2025 UTC |
Hi, I can confirm the bug on Solaris (not OpenSolaris) Version 10 x86_64 # isainfo -b 64 # uname -srvmpi SunOS 5.10 Generic_118855-33 i86pc i386 i86pc # Results with unpatched 64 Bit PHP 5.2.8: # php5 -r "var_dump(ip2long('example.com'));" int(4294967295) # WRONG, should be bool(false), this is not a valid IP # php5 -r "var_dump(ip2long(\"1\x00x\"));" int(1) # correct? # php5 -r "var_dump(ip2long('0.1'));" int(1) # correct? # php5 -r "var_dump(ip2long(''));" bool(false) # correct # php5 -r "var_dump(ip2long('0.0.0.0'));" int(0) # correct # php5 -r "var_dump(ip2long('0.0.0.1'));" int(1) # correct # php5 -r "var_dump(ip2long('1.2.3.4'));" int(16909060) # correct # php5 -r "var_dump(ip2long('4.3.2.1'));" int(67305985) # correct # php5 -r "var_dump(ip2long('255.255.255.254'));" int(4294967294) # correct # php5 -r "var_dump(ip2long('255.255.255.255'));" int(4294967295) # correct There is a problem in PHP function ip2long() with the comparison with INADDR_NONE on 64 bit Solaris systems, since the return value of function inet_addr is stored in an "unsigned long int" variable while struct inet_addr is only 32 bit wide. The "RETURN_FALSE" branch will never be reached when a string like "example.com" is supplied, since the comparison of ip and INADDR_NONE evaluates to false (it should be true in case of error). # Patch worked as expected on Debian GNU/Linux squeeze x86_64 with PHP 5.2.6: # php5 -r "var_dump(ip2long('example.com'));" bool(false) # correct # php5 -r "var_dump(ip2long(\"1\x00x\"));" int(1) # correct? # php5 -r "var_dump(ip2long('0.1'));" int(1) # correct? # php5 -r "var_dump(ip2long(''));" bool(false) # correct # php5 -r "var_dump(ip2long('0.0.0.0'));" int(0) # correct # php5 -r "var_dump(ip2long('0.0.0.1'));" int(1) # correct # php5 -r "var_dump(ip2long('1.2.3.4'));" int(16909060) # correct # php5 -r "var_dump(ip2long('4.3.2.1'));" int(67305985) # correct # php5 -r "var_dump(ip2long('255.255.255.254'));" int(4294967294) # correct # php5 -r "var_dump(ip2long('255.255.255.255'));" int(4294967295) # correct I propose the following patch to simplify the code and fix the problem at the same time. Will this code work on all platforms (Linux, Solaris, BSD, Windows, etc.)? Your hints and suggestions are welcome. -------------------- start of patch -------------------- diff -ru php-5.2.9.orig/ext/standard/basic_functions.c php-5.2.9/ext/standard/basic_functions.c --- php-5.2.9.orig/ext/standard/basic_functions.c 2008-12-31 12:17:44.000000000 +0100 +++ php-5.2.9/ext/standard/basic_functions.c 2009-03-25 19:00:15.000000000 +0100 @@ -97,10 +97,6 @@ # include "win32/unistd.h" #endif -#ifndef INADDR_NONE -#define INADDR_NONE ((unsigned long int) -1) -#endif - #include "zend_globals.h" #include "php_globals.h" #include "SAPI.h" @@ -4336,7 +4332,7 @@ PHP_FUNCTION(ip2long) { zval **str; - unsigned long int ip; + struct in_addr addr; if (ZEND_NUM_ARGS() != 1 || zend_get_parameters_ex(1, &str) == FAILURE) { WRONG_PARAM_COUNT; @@ -4344,20 +4340,11 @@ convert_to_string_ex(str); - if (Z_STRLEN_PP(str) == 0 || (ip = inet_addr(Z_STRVAL_PP(str))) == INADDR_NONE) { - /* the only special case when we should return -1 ourselves, - * because inet_addr() considers it wrong. We return 0xFFFFFFFF and - * not -1 or ~0 because of 32/64bit issues. - */ - if (Z_STRLEN_PP(str) == sizeof("255.255.255.255") - 1 && - !memcmp(Z_STRVAL_PP(str), "255.255.255.255", sizeof("255.255.255.255") - 1)) { - RETURN_LONG(0xFFFFFFFF); - } - - RETURN_FALSE; - } + if (Z_STRLEN_PP(str) == 0 || inet_pton(AF_INET, Z_STRVAL_PP(str), &addr) != 1) { + RETURN_FALSE; + } - RETURN_LONG(ntohl(ip)); + RETURN_LONG(ntohl(addr.s_addr)); } /* }}} */ -------------------- end of patch -------------------- Kind regards, Daniel