php.net |  support |  documentation |  report a bug |  advanced search |  search howto |  statistics |  random bug |  login
Bug #40115 String Comparison shows odd results for integer values around -2^31
Submitted: 2007-01-12 22:19 UTC Modified: 2007-01-16 19:58 UTC
Votes:4
Avg. Score:4.2 ± 0.8
Reproduced:4 of 4 (100.0%)
Same Version:2 (50.0%)
Same OS:3 (75.0%)
From: jannisbreitwieser at web dot de Assigned:
Status: Closed Package: Strings related
PHP Version: 5.2.0 OS: Linux 2.6
Private report: No CVE-ID: None
Welcome back! If you're the original bug submitter, here's where you can edit the bug or add additional notes.
If you forgot your password, you can retrieve your password here.
Password:
Status:
Package:
Bug Type:
Summary:
From: jannisbreitwieser at web dot de
New email:
PHP Version: OS:

 

 [2007-01-12 22:19 UTC] jannisbreitwieser at web dot de
Description:
------------
<?

$a = '-2147483648';
for ($a = -2147373648 ; $a > -2147483670; $a-=1000) {
$a = (string) $a;
$b = '50000';
echo $a > $b ? "$a - true\n" : "$a - false\n"; 
}

?>

-> The comparison should always return false but it doesnt - for some reason some of the comparisons return true.



Reproduce code:
---------------
according to 
http://www.php.net/manual/en/language.operators.comparison.php

Quote:"If you compare two numerical strings, they are compared as integers."

This is not the case since

$a = '-2147483648';
for ($a = -2147373648 ; $a > -2147483670; $a-=1000) {
// No longer cast to string
$b = '50000';
echo $a > $b ? "$a - true\n" : "$a - false\n"; 
}

returns different values (which is 'false' as expected).


Patches

Pull Requests

History

AllCommentsChangesGit/SVN commitsRelated reports
 [2007-01-12 22:23 UTC] tony2001@php.net
Integers tend to overflow and this is expected.
 [2007-01-13 11:41 UTC] jannisbreitwieser at web dot de
I?m afraid the answert doesn?t explain php?s odd behavior.
Just run the code on the bottom and try to figure out its behavior.
It?s definitely not as it should be!

String-String Comparisons are handley incorrectly internally somehow.
Int-Int Comparisons also work without being affected by overflows.

Run This:
/////////////////////////////

<?PHP
error_reporting ( 63 );

echo "\n";

$a = 2147483648;
var_dump($a);
$a = 2147483647;
var_dump($a);
$a = -2147483648;
var_dump($a); // WTF?
$a = -2147483647;
var_dump($a);
echo "\n";

function print_results( $a, $b ) {
 $c = $a - $b;
// var_dump($a);
// var_dump($b);
 echo sprintf( " %7s>%7s", gettype($a), gettype($b) ) .
      " | " . ( $a>$b ? "true " : "false" ) .
      " | " . "a-b = "; var_dump($c);
}

echo '$a as an int  - unexpected results ';

for ($b = -2; $b <= 2; $b+=1) {

 $a = '-2147483647'; // the strings number value of $a is an int for php - see above
 $b = (string)$b;
 echo "$a>$b:\n";

 echo "\n";

 $a = (string)$a;
 $b = (string)$b;
 print_results( $a, $b );

 $a = (int)$a;
 $b = (string)$b;
 print_results( $a, $b );
$a = (string)$a;
 $b = (int)$b;
 print_results( $a, $b );

 $a = (int)$a;
 $b = (int)$b;
 print_results( $a, $b );

 echo "\n";

}

echo '$a as a fake float - unexpected results';

for ($b = -2; $b <= 2; $b+=1) {

 $a = '-2147483648'; // This time $a is a float for php - still wrong result, probably its internally handled as an int since pow(2,-31) is still in the int range of normal programming languages like c
 $b = (string)$b;
 echo "$a>$b:\n";

 echo "\n";

 $a = (string)$a;
 $b = (string)$b;
 print_results( $a, $b );

 $a = (int)$a;
 $b = (string)$b;
 print_results( $a, $b );

 $a = (string)$a;
 $b = (int)$b;
 print_results( $a, $b );

 $a = (int)$a;
 $b = (int)$b;
 print_results( $a, $b );

 echo "\n";

}

echo '$a as a real float - results as expected';
for ($b = -2; $b <= 2; $b+=1) {
 $a = '-2147483649'; // This time the number value of $a is a "real" float since it is out of a normal integers range. - results are as expected.
 $b = (string)$b;
 echo "$a>$b:\n";

 echo "\n";

 $a = (string)$a;
 $b = (string)$b;
 print_results( $a, $b );

 $a = (int)$a;
 $b = (string)$b;
 print_results( $a, $b );

 $a = (string)$a;
 $b = (int)$b;
 print_results( $a, $b );

 $a = (int)$a;
 $b = (int)$b;
 print_results( $a, $b );

 echo "\n";

}



?>
 [2007-01-13 15:32 UTC] iliaa@php.net
Thank you for taking the time to write to us, but this is not
a bug. Please double-check the documentation available at
http://www.php.net/manual/ and the instructions on how to report
a bug at http://bugs.php.net/how-to-report.php

This is due to integer overflow.
 [2007-01-13 17:56 UTC] jannisbreitwieser at web dot de
Hi again.

I?m not sure if you dont understand me or if I don?t understand you.

To quote the manual:
http://www.php.net/manual/en/language.operators.comparison.php
"If you compare an integer with a string, the string is converted to a number. If you compare two numerical strings, they are compared as integers."

The comparison table on the same page says for string comparison: "Translate strings and resources to numbers, usual math"

This implies to me that 

the comparison:
" -2147483648>1:"  has got the same result for integers and string.

(string) -2147483648 >  (string) 1 -->  true  
(int) -2147483648 > (int)  1 --> false

Please try to explain to me why this is not the case.
Either there is a bug in the documentation or there is a bug in the implementation. But obviously implementation and documentation do not match.
 [2007-01-15 04:39 UTC] php_lists at realplain dot com
Tony and Ilia, yes this IS from integer overflow but it's a bug in zendi_smart_strcmp(). Ilia, remember I sent the patch to fix this just a couple weeks ago? ;-) See v1.208.2.4.2.18 of zend_operators.c: http://cvs.php.net/viewvc.cgi/ZendEngine2/zend_operators.c?r1=1.208.2.4.2.17&r2=1.208.2.4.2.18&view=patch

The same bug was fixed with non-string integers over 6 years ago, in v1.90.

To the bug reporter, have you tried PHP 5.2.1RC2? I think you'll find these things work as expected there. :-) BTW, on your "WTF?" var_dump(), that's a float because the number is parsed on its own in scripts (without the "-"), and then negated in another operation. As a string however, it's all converted at once so it's still an integer. If that helps explain things there...
 [2007-01-15 09:41 UTC] tony2001@php.net
var_dump((string) -2147483648 > (string) 1); //bool(false)
var_dump((int) -2147483648 > (int) 1); //bool(false)

what are you talking about?

 [2007-01-15 10:35 UTC] jannisbreitwieser at web dot de
@php_lists at realplain dot com:

Thank you for the first elaborate attempt to answer my problem.

I did not try 5.2.1 yet 
afaik 5.2.0 is the current offical version.

@tony: I don?t know which version you are using.
This report is for version 5.2.0 on linux where the problem definitely still occurs:

user@machine:~$ php -v
PHP 5.2.0 (cli) (built: Jan 01 2007 15:28:45) 
Copyright (c) 1997-2006 The PHP Group
Zend Engine v2.2.0, Copyright (c) 1998-2006 Zend Technologies
user@machine:~$ cat test.php 
<?

var_dump((string) -2147483648 > (string) 1); //bool(true)
var_dump((int) -2147483648 > (int) 1); //bool(false)

?>
user@machine:~$ php test.php 
bool(true)
bool(false)
 [2007-01-16 19:58 UTC] jannisbreitwieser at web dot de
just wanted to mention that this problem ist NOT fixed in the dev versions of php 4.x and 6.x
 
PHP Copyright © 2001-2025 The PHP Group
All rights reserved.
Last updated: Sat Jul 26 21:00:02 2025 UTC