php.net |  support |  documentation |  report a bug |  advanced search |  search howto |  statistics |  random bug |  login
Bug #47246 xor,~ bitwise operations are not 32 bit
Submitted: 2009-01-29 21:17 UTC Modified: 2009-02-01 09:04 UTC
Votes:2
Avg. Score:5.0 ± 0.0
Reproduced:2 of 2 (100.0%)
Same Version:0 (0.0%)
Same OS:2 (100.0%)
From: helpmepro1 at gmail dot com Assigned:
Status: Not a bug Package: Scripting Engine problem
PHP Version: 5.1.6 OS: linux
Private report: No CVE-ID: None
 [2009-01-29 21:17 UTC] helpmepro1 at gmail dot com
Description:
------------
the problem is doing bitwise operations with large numbers like larger then 28 bit.

when i do 
negative bitwise operation "~" to 4738698913
in binary
11010011100101100111010100001{29bit}
the number becomes binary
10000000000000000000000000000000{32bit} 

expected:
11100101100011010011000101011110



Reproduce code:
---------------
<TEXTAREA STYLE="height:98%;width:98%">
<?php
//

//I think I found out the solution by using GMP function.
//Code:
function gxor($a,$b)
{
 $a=gmp_init("$a",10);
 $b=gmp_init("$b",10);
 return gmp_strval (gmp_xor ($a, $b),10);
}

echo "gxor(-5799680607,167160) = ".gxor(-5799680607,167160)."\n";
echo "                 as expected -5799843495 \n";
echo "     -5799680607^167160  = " .(-5799680607^167160)."\n";
echo "                 wrong result \n\n";
 
echo "var_dump(-4738698913) = ";
var_dump(-4738698913);
echo "so this number is float\n\n";
 
echo "A decbin              43814   SIMPLE       = ".decbin(43814)."\n\n"; //a
echo "B decbin        -4738698913   NOT WORKING  = ".decbin(-4738698913)."\n\n"; //b 
echo "C decbin         4738698913   SIMPLE       = ".decbin(4738698913)."\n\n";
echo "D decbin abs    -4738698913   WORKING      = ".decbin(abs(-4738698913))."\n\n";
echo "E decbin ~abs   -4738698913   NOT WORKING  = ".decbin(~abs(-4738698913))."\n\n";
echo "F decbin ~abs   -1738698913   WORKING      = ".decbin(~abs(-1738698913))."\n\n";
echo "G decbin ~      -4738698913   64bit expected result: 1111111111111111111111111111111011100101100011010011000101011110\n";
echo "H the 64bit bitwise not is from windows calc.exe\n\n";
echo "from the B and G example i can deduce that php takes the left side of 64 bit integer instead of the right and returns it as 32 bit (just a guess)\n\n";
// 1111111111111111111111111111111011100101100011010011000101011110

echo "php version ".PHP_VERSION;
echo "\n";
echo `cat /proc/version`;
echo "\n";
echo `cat /proc/cpuinfo`;
echo "\n";
?>
</TEXTAREA>

Expected result:
----------------
gxor(-5799680607,167160) = -5799843495
                 as expected -5799843495 
     -5799680607^167160  = -2147316488
                 wrong result 

var_dump(-4738698913) = float(-4738698913)
so this number is float

A decbin              43814   SIMPLE       = 1010101100100110

B decbin        -4738698913   NOT WORKING  = 10000000000000000000000000000000

C decbin         4738698913   SIMPLE       = 11010011100101100111010100001

D decbin abs    -4738698913   WORKING      = 11010011100101100111010100001

E decbin ~abs   -4738698913   NOT WORKING  = 1111111111111111111111111111111

F decbin ~abs   -1738698913   WORKING      = 10011000010111011000111101011110

G decbin ~      -4738698913   64bit expected result: 1111111111111111111111111111111011100101100011010011000101011110
H the 64bit bitwise not is from windows calc.exe

from the B and G example i can deduce that php takes the left side of 64 bit integer instead of the right and returns it as 32 bit (just a guess)


Actual result:
--------------
php version 5.1.6
Linux version 2.6.18-92.1.18.el5PAE (mockbuild@builder16.centos.org) (gcc version 4.1.2 20071124 (Red Hat 4.1.2-42)) #1 SMP Wed Nov 12 10:02:30 EST 2008

processor	: 0
vendor_id	: GenuineIntel
cpu family	: 6
model		: 23
model name	: Intel(R) Xeon(R) CPU           E5405  @ 2.00GHz
stepping	: 6
cpu MHz		: 1995.120
cache size	: 6144 KB
physical id	: 0
siblings	: 4
core id		: 0
cpu cores	: 4
fdiv_bug	: no
hlt_bug		: no
f00f_bug	: no
coma_bug	: no
fpu		: yes
fpu_exception	: yes
cpuid level	: 10
wp		: yes
flags		: fpu vme de pse tsc msr pae mce cx8 apic sep mtrr pge mca cmov pat pse36 clflush dts acpi mmx fxsr sse sse2 ss ht tm pbe nx lm constant_tsc pni monitor ds_cpl vmx tm2 cx16 xtpr lahf_lm
bogomips	: 3992.34

Patches

Add a Patch

Pull Requests

Add a Pull Request

History

AllCommentsChangesGit/SVN commitsRelated reports
 [2009-01-29 21:37 UTC] helpmepro1 at gmail dot com
on windows it works like this:

var_dump(-4738698913) = float(-4738698913)
so this number is float

A decbin              43814   SIMPLE       = 1010101100100110

B decbin        -4738698913   NOT WORKING  = 11100101100011010011000101011111

C decbin         4738698913   SIMPLE       = 11010011100101100111010100001

D decbin abs    -4738698913   WORKING      = 11010011100101100111010100001

E decbin ~abs   -4738698913   NOT WORKING  = 11100101100011010011000101011110

F decbin ~abs   -1738698913   WORKING      = 10011000010111011000111101011110

php version 4.4.4
 [2009-01-29 21:41 UTC] helpmepro1 at gmail dot com
on windows it works OK maybe there is a different cpu i dont know
 [2009-01-31 23:46 UTC] jani@php.net
1. Your PHP versions are too old (current version is 5.2.8, 5.3.0 is 
about to be released..you do the math)
2. Use 64bit machine for 64bit math and it works fine. 
3. Ask further support questions on how to program elsewhere.
 [2009-02-01 09:04 UTC] helpmepro1 at gmail dot com
i can't install new version its a shared server i am hosting at.
i know this bug for years.

i have searched for such bug in PHP bugs and not found it fixed.
i have always found it with Bogus status.

i think it is serious problem that php does not behave the same on every machine.

i expect PHP to work the same on every machine with indifference of the CPU , CPU bits and the operation system.

if CPU does not have 64 bit math i think the bitwise staff should be emulated and work slower or not.
(the normal math works OK)

however this is not the current problem. MY SERVER HAS 64 bit CPU.
and because of that i have a problem in my program 
because i guess : it takes the other register on some CPUSs as the first register when it does bitwise calculations.


i have tried to give you very detailed information about the bug.
and my 
can you check please if bitwise 64bit emulation exists in php?

my solution was to truncate the number correctly by doing normal math until 32 bit count.

// decrypt
function TEAdecrypt($str, $key) {
 $str = ew_UrlDecode($str);
 if ($str == "") {
  return "";
 }
 $v = str2long($str, false);
 $k = str2long($key, false);
 if (count($k) < 4) {
  for ($i = count($k); $i < 4; $i++) {
   $k[$i] = 0;
  }
 }
 $n = count($v) - 1;
 $z = $v[$n];
 $y = $v[0];
 $delta = 0x9E3779B9;
 $q = floor(6 + 52 / ($n + 1));
 $sum = int32($q * $delta);
 while ($sum != 0) {
  $e = $sum >> 2 & 3;
  for ($p = $n; $p > 0; $p--) {
   $z = $v[$p - 1];
   $mx = int32((($z >> 5 & 0x07ffffff) ^ $y << 2) + (($y >> 3 & 0x1fffffff) ^ $z << 4)) ^ int32(($sum ^ $y) + ($k[$p & 3 ^ $e] ^ $z));
   $y = $v[$p] = int32($v[$p] - $mx);
  }
  $z = $v[$n];
  $mx = int32((($z >> 5 & 0x07ffffff) ^ $y << 2) + (($y >> 3 & 0x1fffffff) ^ $z << 4)) ^ int32(($sum ^ $y) + ($k[$p & 3 ^ $e] ^ $z));
  $y = $v[0] = int32($v[0] - $mx);
  $sum = int32($sum - $delta);
 }
 return long2str($v, true);
}

function int32($n) {
 while ($n >= 2147483648) $n -= 4294967296;
 while ($n <= -2147483649) $n += 4294967296;
 return (int)$n;
}
 
PHP Copyright © 2001-2019 The PHP Group
All rights reserved.
Last updated: Mon Nov 11 22:01:32 2019 UTC