Typecasting in ArrayObject::offsetGet and ArrayObject::offsetSet
| From: | Alex S Kurilo | Date: | Tue, 31 May 2011 15:59:09 +0000 |
| Subject: | Typecasting in ArrayObject::offsetGet and ArrayObject::offsetSet | ||
| Groups: | php.internals | ||
| Request: | Send a blank email to internals+get-52565@lists.php.net to get a copy of this message | ||
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: [application/x-httpd-php] array_object_error.php
--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: [application/x-httpd-php] array_object_error.php