Skip to content

Negative indices on empty array don't affect next chosen index #11154

Closed
@ColinHDev

Description

@ColinHDev

Description

I was browsing through php's source code to look at how arrays work and noticed the following:

This code:

<?php
$a = array();
$a[-5] = "-5";
$a[] = "after -5";

behaves differently than this code:

<?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

Metadata

Metadata

Assignees

No one assigned

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions