Hello.

Typecasting on the index passed to ArrayObject::offsetGet and ArrayObject::offsetSet seems to be the reason of ArrayObject's confusing behavior on x86 systems.

According to http://php.net/manual/en/language.types.integer.php#language.types.integer.overflow,

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.

So, integer is casted to float, then it's passed to ArrayObject::offsetSet and is casted back to integer, probably due to the following lines (ext/spl/spl_array.c:348):
                 if (offset->type == IS_DOUBLE) {
                         index = (long)Z_DVAL_P(offset);
                 } else {
                         index = Z_LVAL_P(offset);
                 }

As a result of calling ArrayObject::offsetSet(index, value) on x86 with a float index exceeds 'long', value appears under a non-obvious index and is replaced on every other call with greater than 'long' index.

Tests are attached. test_array.phpt is passed on both x86 and x86_64, test_array_object.phpt fails to pass on x86 (but is passed on x86_64). This difference in array's and ArrayObject's behavior made me to consider this a bug.

array_object_error.php on x86 just makes pretty clear the reason of fail (see notices PHP throws).
--TEST--
test 1
--FILE--
<?php
//$array = new ArrayObject;
$array = array();

$key1 = 1e9;
$key2 = $key1 * 10;
$key3 = $key2 + 1;
$array[$key1] = "a";
$array[$key2] = "b";
$array[$key3] = "c";

echo $array[$key1],$array[$key2],$array[$key3];
--EXPECT--
abc
--TEST--
test 1
--FILE--
<?php
$array = new ArrayObject;
//$array = array();

$key1 = 1e9;
$key2 = $key1 * 10;
$key3 = $key2 + 1;
$array[$key1] = "a";
$array[$key2] = "b";
$array[$key3] = "c";

echo $array[$key1],$array[$key2],$array[$key3];
--EXPECT--
abc

<<attachment: array_object_error.php>>

-- 
PHP Internals - PHP Runtime Development Mailing List
To unsubscribe, visit: http://www.php.net/unsub.php

Reply via email to