ID: 40115 Comment by: php_lists at realplain dot com Reported By: jannisbreitwieser at web dot de Status: Open Bug Type: Strings related Operating System: Linux 2.6 PHP Version: 5.2.0 New Comment:
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... Previous Comments: ------------------------------------------------------------------------ [2007-01-13 17:56:17] 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-13 15:32:11] [EMAIL PROTECTED] 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 11:41:44] 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-12 22:23:11] [EMAIL PROTECTED] Integers tend to overflow and this is expected. ------------------------------------------------------------------------ [2007-01-12 22:19:44] 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). ------------------------------------------------------------------------ -- Edit this bug report at http://bugs.php.net/?id=40115&edit=1