[php-src] Issue #11154: Negative indices on empty array don't affect next chosen index
| From: | ColinHDev | Date: | Fri, 28 Apr 2023 10:06:54 +0000 |
| Subject: | [php-src] Issue #11154: Negative indices on empty array don't affect next chosen index | ||
| Groups: | php.bugs | ||
| Request: | Send a blank email to php-bugs+get-244298@lists.php.net to get a copy of this message | ||
Issue: https://github.com/php/php-src/issues/11154
Author: ColinHDev
### Description
I was browsing through php's source code to look at how arrays work and noticed the following:
This code:
```php
<?php
$a = array();
$a[-5] = "-5";
$a[] = "after -5";
```
behaves differently than this code:
```php
<?php
$b = array(
-5 => "-5"
);
$b[] = "after -5";
```
Resulted in this output:
```
array(2) {
[-5]=>
string(2) "-5"
[0]=>
string(8) "after -5"
}
array(2) {
[-5]=>
string(2) "-5"
[-4]=>
string(8) "after -5"
}
```
But I expected this output instead:
```
array(2) {
[-5]=>
string(2) "-5"
[-4]=>
string(8) "after -5"
}
array(2) {
[-5]=>
string(2) "-5"
[-4]=>
string(8) "after -5"
}
```
https://3v4l.org/MjbOm
I am not sure, if this is a bug or intended, so I wanted to create an issue regarding that.
The PR #3772 changed that appending to arrays would also work if the previous element has a negative
index without defaulting to 0 in that case.
It did so by setting the default value for
nNextFreeElement from 0 to
ZEND_LONG_MIN, while also adding the following "guard clause" to the
_zend_hash_index_add_or_update_i( ) function, which makes sure that the chosen index
defaults to 0 if it's still at ZEND_LONG_MIN and the element should
be put at the next index. https://github.com/php/php-src/blob/master/Zend/zend_hash.c#L1027-L1029.
But it did not change that for the _zend_empty_array constant: https://github.com/php/php-src/blob/master/Zend/zend_hash.c#L258.
Because of that, the following if statement is always false for empty arrays since
(any_negative_key >= 0) == false: https://github.com/php/php-src/blob/master/Zend/zend_hash.c#L1110-L1112.
My question is, is this intended? Because it looks like a bug to me, especially since that
"guard clause" would ensure that running $a[] = "" on an empty
array, would still use index 0.
But I am not familiar with the PHP internals, so I might have completely missed something. So if
there is a reason for this behaviour or why _zend_empty_array's
nNextFreeElement can't start at ZEND_LONG_MIN, I would be happy to
know why!
### PHP Version
PHP 8.2.3
### Operating System
_No response_