ID:               47365
 Updated by:       j...@php.net
 Reported By:      flobee at gmail dot com
-Status:           Open
+Status:           Assigned
 Bug Type:         Network related
 Operating System: SunOS
 PHP Version:      5.2.9
-Assigned To:      
+Assigned To:      dsp


Previous Comments:
------------------------------------------------------------------------

[2009-03-26 01:22:34] pada at hrz dot tu-chemnitz dot de

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

------------------------------------------------------------------------

[2009-02-12 13:09:49] d...@php.net

Not enough information was provided for us to be able
to handle this bug. Please re-read the instructions at
http://bugs.php.net/how-to-report.php

If you can provide more information, feel free to add it
to this bug and change the status back to "Open".

Thank you for your interest in PHP.


Which Solaris Version. Solaris 10. On Sparc or on x86?

On OpenSolaris x86 64 bit it returns false as expected:

~/> php -r "var_dump(ip2long('web.de'));"                              
       
bool(false)
~/> isainfo -b                                                         
       
64
~/> uname -a                                                           
       
SunOS Stanford 5.11 snv_106 i86pc i386 i86pc Solaris
~/> php -v                                                             
       
PHP 5.2.6 (cli) (built: Jan 28 2009 01:43:42) (DEBUG)
Copyright (c) 1997-2008 The PHP Group
Zend Engine v2.2.0, Copyright (c) 1998-2008 Zend Technologies


------------------------------------------------------------------------

[2009-02-12 09:27:18] 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




------------------------------------------------------------------------


-- 
Edit this bug report at http://bugs.php.net/?id=47365&edit=1

Reply via email to