Edit report at https://bugs.php.net/bug.php?id=69693&edit=1
ID: 69693
Updated by: nikic@php.net
Reported by: bugs at tmarques dot com
Summary: Reproducible Corruption on Variables
Status: Open
Type: Bug
Package: *General Issues
Operating System: Linux x32
PHP Version: 5.5.25
Block user comment: N
Private report: N
New Comment:
For the record, PHP 7 is now mostly working on x32 as well. I've landed some tweaks in https://github.com/php/php-src/commit/f3dde29394831c59fc927bd5e7a7800a3fbe8519
which make nearly all tests pass - there's two or three failures left due to wrong
size_t/zend_long usage resulting in overflows.
I went for making PHP integers 64bit - this integrates very nicely with how zend_long is currently
used (all our assembly is still correct) and I think this is what PHP programmers would want to
have. But not totally sure if this is the right choice.
Previous Comments:
------------------------------------------------------------------------
[2015-05-25 01:32:12] bugs at tmarques dot com
Forgot to mention I'll be looking at the rest of the tests to see if I can fix them. Pointers
to the Date issues would be useful.
------------------------------------------------------------------------
[2015-05-25 01:27:28] bugs at tmarques dot com
Managed to fix some stuff, though they're mostly hacks to always run i386 code.
Current problem is most of the Zend operators are passing 64bit instructions to x32 PHP, so I just
#if'd them to add ILP32 checks to the i386 assembly instead. I think this is mostly correct
(not optimized) but x86-64 assembly has the same issue with these x32 changes: it is still using x87
instead of the faster SSE2, as it should on x86-64 capable CPUs.
From looking at the current code, I didn't understand why the FPU is being used to calculate
integer operations (this shouldn't be faster).
I also think there might be problems with the 'safe_address' function in
'Zend/zend_alloc.c', as it has LP_SUFF defined for the 'mul' instruction, as it
should, but uses both 'add/adc'. My understanding from the manuals is that this is correct
if the operands to the instruction are 32bit for x32, then all will be ok, while 64bit operands will
execute as 64bit. Still, if this is a mixup of AT&T and Intel syntax for opcodes, it should
probably be unified and checked for correct word size on the parameters.
Below are the results of 'make test' before and after the patch submitted, which shows no
regressions. The test case I submitted also passes now.
=====================================================================
FAILED TEST SUMMARY
---------------------------------------------------------------------
Bug #24054 (Assignment operator *= broken) [tests/lang/bug24054.phpt]
Test >= operator : max int 32bit range [tests/lang/operators/operator_gt_or_equal_variation.phpt]
Test > operator : max int 32bit range [tests/lang/operators/operator_gt_variation.phpt]
Test <= operator : max int 32bit range [tests/lang/operators/operator_lt_or_equal_variation.phpt]
Test < operator : max int 32bit range [tests/lang/operators/operator_lt_variation.phpt]
Bug #45877 (Array key '2147483647' left as string) [Zend/tests/bug45877.phpt]
decrementing different variables [Zend/tests/decrement_001.phpt]
incrementing different variables [Zend/tests/increment_001.phpt]
Bug #41523 (strtotime('0000-00-00 00:00:00') is parsed as 1999-11-30) (32 bit)
[ext/date/tests/bug41523.phpt]
Test getdate() function : usage variation - Passing high positive and negative float values to
timestamp. [ext/date/tests/getdate_variation7.phpt]
Test localtime() function : usage variation - Passing higher positive and negetive float values to
timestamp. [ext/date/tests/localtime_variation3.phpt]
Test array_sum() [ext/standard/tests/array/array_sum.phpt]
Bug #65304 (Use of max int in array_sum) [ext/standard/tests/array/bug65304.phpt]
Simple math tests [ext/standard/tests/math/abs.phpt]
Various pow() tests [ext/standard/tests/math/pow.phpt]
Simple math tests [ext/standard/tests/math/round.phpt]
Bug #64146 (serialize incorrectly saving objects when they are cloned)
[ext/standard/tests/serialize/bug64146.phpt]
=====================================================================
Patched:
=====================================================================
FAILED TEST SUMMARY
---------------------------------------------------------------------
Bug #41523 (strtotime('0000-00-00 00:00:00') is parsed as 1999-11-30) (32 bit)
[ext/date/tests/bug41523.phpt]
Test getdate() function : usage variation - Passing high positive and negative float values to
timestamp. [ext/date/tests/getdate_variation7.phpt]
Test localtime() function : usage variation - Passing higher positive and negetive float values to
timestamp. [ext/date/tests/localtime_variation3.phpt]
Bug #64146 (serialize incorrectly saving objects when they are cloned)
[ext/standard/tests/serialize/bug64146.phpt]
=====================================================================
------------------------------------------------------------------------
[2015-05-23 08:28:59] nikic@php.net
I don't think we currently really support the x32 ABI. You're likely tripping over some
inline assembly that is not properly #if'd.
------------------------------------------------------------------------
[2015-05-23 00:36:48] bugs at tmarques dot com
Sure, it's small values. Real code was $i=68 and $l=71, IIRC. You can see the test case on the
Gist I posted in the description on the bug. There it returns a float with smaller integers. What
should have been 10 or so becomes 9.xx*10^18, something like that.
As I mentioned, all code runs fine in i686 but "blows up" on x32 ABI (which is quite
useful no virtualized servers).
------------------------------------------------------------------------
[2015-05-22 22:30:34] danack@php.net
"two variables that have integers get summed and return a float."
Yes - this is the defined behaviour for when an operation occurs and the result is no longer
representable as an integer type. e.g.
<?php
$x = PHP_INT_MAX;
$x += 1;
var_dump($x);
?>
Will say that $x is a float value. Or to quote from the manual - http://php.net/manual/en/language.types.integer.php
"If PHP encounters a number beyond the bounds of the integer type, it will be interpreted as a
float instead. Also, an operation which results in a number beyond the bounds of the integer type
will return a float instead."
If you think the conversion from int to float is occurring inappropriately, please can you provide a
simple reproduction case?
------------------------------------------------------------------------
The remainder of the comments for this report are too long. To view
the rest of the comments, please view the bug report online at
https://bugs.php.net/bug.php?id=69693
--
Edit this bug report at https://bugs.php.net/bug.php?id=69693&edit=1