php.net |  support |  documentation |  report a bug |  advanced search |  search howto |  statistics |  random bug |  login
Bug #29874 Bitwise right shift operator produces inconsistent results cross platforms.
Submitted: 2004-08-28 06:27 UTC Modified: 2004-09-19 01:00 UTC
From: binhqx at mac dot com Assigned:
Status: No Feedback Package: *Math Functions
PHP Version: Irrelevant OS: OS X Server 10.3 (Darwin 7.5.0)
Private report: No CVE-ID: None
View Add Comment Developer Edit
Welcome! If you don't have a Git account, you can't do anything here.
You can add a comment by following this link or if you reported this bug, you can edit this bug over here.
(description)
Block user comment
Status: Assign to:
Package:
Bug Type:
Summary:
From: binhqx at mac dot com
New email:
PHP Version: OS:

 

 [2004-08-28 06:27 UTC] binhqx at mac dot com
Description:
------------
Bitwise right shift operator produces incorrect result 
when applied to a double in all version of PHP on OS X.

During a bitwise right shift, the php processor casts 
the  operand

Reproduce code:
---------------
$operand = 8726521066;
echo ($operand >> 10);

Expected result:
----------------
133385

Actual result:
--------------
-1

Patches

Add a Patch

Pull Requests

Add a Pull Request

History

AllCommentsChangesGit/SVN commitsRelated reports
 [2004-08-28 06:35 UTC] binhqx at mac dot com
Original description was cutoff:

Bitwise right shift operator produces incorrect result 
when applied to a double in all version of PHP on OS X.

During a bitwise right shift, the php processor casts 
the operand to a integer.  Most of the time this works
fine, but when the value of the operand is greater the 
32 bits, the variable is chopped to just the last 32
bits. This is the way it should work.
For example: 136586474 >> 10 becomes 133385

Under OS X Server, this casting procedure does not work 
the same way. When value of the operand is greater then 
32
bits, the variable is changed to the largest posable 
value of a integer (2^32). Because all integers are 
signed
this is -1. 8726521066 >> 10 becomes -1

I have tested the the shift operator on Linux using PHP 
4.1.2 - 4.3.4 and it produces the correct results. On OS
X/OS X Server (Darwin 7.5.0) using PHP 4.3.2 - 5.0.1 and 
it produces the incorrect results.

It would appear the bug only exists in the OS X port of 
PHP.

Examples:
Testing OS X Server: http://worldvoicellc.net/
bitshift_test.php

Testing Linux: http://12.160.216.20/altigen/phptest/
bitshift_test.php

Testing code: http://worldvoicellc.net/bitshift_test.txt
 [2004-08-28 06:50 UTC] binhqx at mac dot com
I did some more searching through the bug archive and 
found many bugs pertaining to logic operator and 
doubles.   

Before I get redirected to one of those, I would like to 
emphasize that this is not a problem with the value 
being produced. The problem is the same operation is 
producing different results on different platforms.
 [2004-08-29 03:51 UTC] binhqx at mac dot com
I did some digging in the code using gdb and found the 
root of the problem likly resides in 
zend_operators.c in shift_right_function().

On line 1108 of zend_operators.c the 
zendi_convert_to_long macro is called then the 
DVAL_TO_LVAL macro.

To me, it looks like inconsistency occurs here:
zend_operators.c:186
#define DVAL_TO_LVAL(d, l) (l) = (d) > LONG_MAX ? 
(unsigned long) (d) : (long) (d)

When d is greater then LONG_MAX, d is cast as a unsigned 
long. When the value is then copied into 
op1_copy.value.lval, it is recast as to a long.

The bug appears to be with the OS.

Here is some code to show the inconsistency:
--------------
#include <iostream>
using namespace std;

int main (int argc, char * const argv[]) {

	double large_number = 8e10;

    cout << "Casting Test\n";
	cout << "double = "			<< large_number	
	<< "\n";
	cout << "unsigned long = "  << (unsigned long 
int)large_number	<< "\n";
	cout << "long  = "			<< (long int)(unsigned 
long int)large_number		<< "\n";

    return 0;
} 
--------------

OS X result:
--------------
Casting Test
double = 8e+10
unsigned long = 4294967295
long  = -1

Linux result:
--------------
Casting Test
double = 8e+10
unsigned long = 2690588672
long  = -1604378624


It looks like this is a OS X bug rather then a PHP bug.

Does any one know of workaround code to make OS X act 
like Linux in PHP or C?
 [2004-09-11 13:51 UTC] tony2001@php.net
Please try using this CVS snapshot:

  http://snaps.php.net/php5-STABLE-latest.tar.gz
 
For Windows:
 
  http://snaps.php.net/win32/php5.0-win32-latest.zip

Please, try latest 5.0 & 5.1 snapshots - there were some changes in zend_operators.c
(but I doubt they can solve the problem in OS..)
 [2004-09-19 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".
 [2009-12-29 14:53 UTC] hwilliams at openlinksw dot com
Has this issue been resolved or cause determined at it still appears to be occurring with the latest PHP 5.2.11 builds on Mac OS X 10.6 i386:

$ uname -a
Darwin name.local 10.2.0 Darwin Kernel Version 10.2.0: Tue Nov  3 10:37:10 PST 2009; root:xnu-1486.2.11~1/RELEASE_I386 i386
 
PHP Copyright © 2001-2024 The PHP Group
All rights reserved.
Last updated: Fri Apr 19 21:01:30 2024 UTC