php.net |  support |  documentation |  report a bug |  advanced search |  search howto |  statistics |  random bug |  login
Bug #47092 Bitwise operation number overflow
Submitted: 2009-01-13 22:00 UTC Modified: 2009-10-16 01:00 UTC
Votes:3
Avg. Score:3.7 ± 0.9
Reproduced:3 of 3 (100.0%)
Same Version:1 (33.3%)
Same OS:1 (33.3%)
From: erik at ekriirke dot com Assigned:
Status: No Feedback Package: Scripting Engine problem
PHP Version: 5.2.8 OS: *
Private report: No CVE-ID: None
 [2009-01-13 22:00 UTC] erik at ekriirke dot com
Description:
------------
This happens the same on Linux (RHE5) and Windows (Server2K,XPPro)
Differing versions of MySQL as well (5.0.51a, 5.1.11)
Using either MySQLi or MySQL extensions

I have a table with an UNSIGNED INTEGER column.  The value in the column has a value where MSB (31) is set (0x80000000 and higher).

Selecting this value into an array via either mysql_fetch_assoc, mysql_fetch_row (and mysqli variant) stores the value correctly as displayed by either a print_r or echo'ing directly.

Should I perform a math operation (+-*/) the result is correct.

Should I perform a bitwise operation  or function the answers are wrong.  It appears doing so internally changes the selected value to 0x7FFFFFFF no matter its original value as long as bit 31 is set.

However, if I perform math on the value THEN a bitwise operation, the result is correct.

Now, I know the MSB is a touchy subject in 31bit math, but there is inconsistency here.

Reproduce code:
---------------
$q=mysql_query("SELECT val FROM test"); // val is an UNSIGED INT containing a value with MSB set.  Ex:  2147488308 (0x80001234)
$a=mysql_fetch_assoc($q);
echo $a['val'],"<br>\n";    //2147488308 - correct
echo dechex($a['val']),"<br>\n";    //7fffffff - wrong

echo $a['val']+0,"<br>\n";    //2147488308 - correct
echo $a['val']+1,"<br>\n";    //2147488309 - correct

echo $a['val']|0,"<br>\n";    //2147483647 - wrong
echo dechex($a['val']+0),"<br>\n";    //80001234 - correct

echo $a['val']&1,"<br>\n";    //1 - wrong
echo ($a['val']+0)&1,"<br>\n";    //0 - correct

/*** Workaround ***/
$a['val']+=0;  //as long as some kind of math was performed it functions correctly afterward

echo $a['val']|0,"<br>\n";    //2147488308 or -2147478988 - correct
echo $a['val']&1,"<br>\n";    //0 - correct
echo dechex($a['val']),"<br>\n";    //80001234 - correct

Expected result:
----------------
2147488308
80001234
2147488308
2147488309
-2147478988
80001234
0
0
-2147478988
0
80001234

Actual result:
--------------
2147488308
7fffffff
2147488308
2147488309
2147483647
80001234
1
0
-2147478988
0
80001234

Patches

Pull Requests

History

AllCommentsChangesGit/SVN commitsRelated reports
 [2009-01-13 22:02 UTC] erik at ekriirke dot com
Just an addendum;  This is only when working with MySQL (from what I have tested), absolutes do not have this problem (eg  echo dechex(0x80001234);)
 [2009-01-13 22:22 UTC] erik at ekriirke dot com
I meant to say "32bit math" is touchy, sorry
 [2009-08-26 12:45 UTC] andrey@php.net
This is not a problem in MySQL, it is a PHP bug or dechex bug.

Here is an example. First, we use a number, than a string with a number. 

andrey@winnie:~/scripts$ php -r '$a=2147488308;print_r($a);echo "\n";print_r($a+1);echo "\n";print_r(dechex($a));echo "\n";'
2147488308
2147488309
80001234


andrey@winnie:~/scripts$ php -r '$a="2147488308";print_r($a);echo "\n";print_r($a+1);echo "\n";print_r(dechex($a));echo "\n";'
2147488308
2147488309
7fffffff

 [2009-08-26 17:04 UTC] erik at ekriirke dot com
Interesting.  So it's PHP itself, and MySQL passes numbers as strings internally?
dechex was just used to make the bits easily readable, though that's not the real issue - try performing bitwise operations in the instances dechex shows all bits high, the result will be wrong:

php -r '$a="2147488308";print_r($a);echo "\n";print_r($a+1);echo "\n";print_r($a&0xFFFF);echo "\n";print_r(dechex($a&0xFFFF));echo "\n";print_r(($a+0)&0xFFFF);echo "\n";print_r(dechex(($a+0)&0xFFFF));echo "\n";'
2147488308
2147488309
65535
ffff
4660
1234

What version are you using, Andre?  Just tested it on Fedora12:
[erik@erik ~]$ php --version
PHP 5.2.9 (cli) (built: Apr 15 2009 09:30:24)
Copyright (c) 1997-2009 The PHP Group
Zend Engine v2.2.0, Copyright (c) 1998-2009 Zend Technologies

...and it appears to work!
However, this newer(!) version (windows vista) still shows the error:

C:\>php --version
PHP 5.2.10 (cli) (built: Jun 17 2009 16:16:57)
Copyright (c) 1997-2009 The PHP Group
Zend Engine v2.2.0, Copyright (c) 1998-2009 Zend Technologies
 [2009-10-08 14:52 UTC] jani@php.net
Wild guess: that linux machine is 64bit whereas windows is 32bit.
In which case there is no bug.
 [2009-10-09 17:35 UTC] erik at ekriirke dot com
Ah, you are right about the 32/64 bit, however you are wrong about there being no bug.
Had you read the thread you would see that only in certain instances it fails to work correctly.  Immediates work perfectly on both architectures, its the passing of such values from mysql(i) functions that fails.

Also discovered is the conversion from string>integer fails.
 [2009-10-16 01:00 UTC] php-bugs at lists dot php dot net
No feedback was provided for this bug for over a week, so it is
being suspended automatically. If you are able to provide the
information that was originally requested, please do so and change
the status of the bug back to "Open".
 
PHP Copyright © 2001-2024 The PHP Group
All rights reserved.
Last updated: Sat Dec 21 16:01:28 2024 UTC