Skip to content

Commit e2c2f6a

Browse files
committed
Implement the negative_array_index RFC
1 parent eeb7511 commit e2c2f6a

File tree

6 files changed

+40
-10
lines changed

6 files changed

+40
-10
lines changed

Zend/zend_hash.c

+9-5
Original file line numberDiff line numberDiff line change
@@ -220,7 +220,7 @@ static zend_always_inline void _zend_hash_init_int(HashTable *ht, uint32_t nSize
220220
ht->nNumUsed = 0;
221221
ht->nNumOfElements = 0;
222222
ht->nInternalPointer = 0;
223-
ht->nNextFreeElement = 0;
223+
ht->nNextFreeElement = ZEND_LONG_MIN;
224224
ht->pDestructor = pDestructor;
225225
ht->nTableSize = zend_hash_check_size(nSize);
226226
}
@@ -935,6 +935,10 @@ static zend_always_inline zval *_zend_hash_index_add_or_update_i(HashTable *ht,
935935
IS_CONSISTENT(ht);
936936
HT_ASSERT_RC1(ht);
937937

938+
if (h == ZEND_LONG_MIN && flag & HASH_ADD_NEXT) {
939+
h = 0;
940+
}
941+
938942
if (HT_FLAGS(ht) & HASH_FLAG_PACKED) {
939943
if (h < ht->nNumUsed) {
940944
p = ht->arData + h;
@@ -999,7 +1003,7 @@ static zend_always_inline zval *_zend_hash_index_add_or_update_i(HashTable *ht,
9991003
Z_NEXT(p->val) = HT_HASH(ht, nIndex);
10001004
HT_HASH(ht, nIndex) = HT_IDX_TO_HASH(idx);
10011005
if ((zend_long)h >= (zend_long)ht->nNextFreeElement) {
1002-
ht->nNextFreeElement = h < ZEND_LONG_MAX ? h + 1 : ZEND_LONG_MAX;
1006+
ht->nNextFreeElement = (zend_long)h < ZEND_LONG_MAX ? h + 1 : ZEND_LONG_MAX;
10031007
}
10041008
add:
10051009
ht->nNumOfElements++;
@@ -1665,7 +1669,7 @@ ZEND_API void ZEND_FASTCALL zend_hash_clean(HashTable *ht)
16651669
}
16661670
ht->nNumUsed = 0;
16671671
ht->nNumOfElements = 0;
1668-
ht->nNextFreeElement = 0;
1672+
ht->nNextFreeElement = ZEND_LONG_MIN;
16691673
ht->nInternalPointer = 0;
16701674
}
16711675

@@ -1704,7 +1708,7 @@ ZEND_API void ZEND_FASTCALL zend_symtable_clean(HashTable *ht)
17041708
}
17051709
ht->nNumUsed = 0;
17061710
ht->nNumOfElements = 0;
1707-
ht->nNextFreeElement = 0;
1711+
ht->nNextFreeElement = ZEND_LONG_MIN;
17081712
ht->nInternalPointer = 0;
17091713
}
17101714

@@ -2018,7 +2022,7 @@ ZEND_API HashTable* ZEND_FASTCALL zend_array_dup(HashTable *source)
20182022
target->nTableMask = HT_MIN_MASK;
20192023
target->nNumUsed = 0;
20202024
target->nNumOfElements = 0;
2021-
target->nNextFreeElement = 0;
2025+
target->nNextFreeElement = ZEND_LONG_MIN;
20222026
target->nInternalPointer = 0;
20232027
target->nTableSize = HT_MIN_SIZE;
20242028
HT_SET_DATA_ADDR(target, &uninitialized_bucket);

ext/standard/array.c

+1-1
Original file line numberDiff line numberDiff line change
@@ -3228,7 +3228,7 @@ PHP_FUNCTION(array_pop)
32283228
}
32293229
ZVAL_COPY_DEREF(return_value, val);
32303230

3231-
if (!p->key && Z_ARRVAL_P(stack)->nNextFreeElement > 0 && p->h >= (zend_ulong)(Z_ARRVAL_P(stack)->nNextFreeElement - 1)) {
3231+
if (!p->key && p->h >= (zend_ulong)(Z_ARRVAL_P(stack)->nNextFreeElement - 1)) {
32323232
Z_ARRVAL_P(stack)->nNextFreeElement = Z_ARRVAL_P(stack)->nNextFreeElement - 1;
32333233
}
32343234

ext/standard/tests/array/array_fill_variation1.phpt

+1-1
Original file line numberDiff line numberDiff line change
@@ -120,7 +120,7 @@ array(2) {
120120
array(2) {
121121
[-10]=>
122122
int(100)
123-
[0]=>
123+
[-9]=>
124124
int(100)
125125
}
126126
-- Iteration 3 --

ext/standard/tests/array/array_fill_variation1_64bit.phpt

+1-1
Original file line numberDiff line numberDiff line change
@@ -120,7 +120,7 @@ array(2) {
120120
array(2) {
121121
[-10]=>
122122
int(100)
123-
[0]=>
123+
[-9]=>
124124
int(100)
125125
}
126126
-- Iteration 3 --

ext/standard/tests/array/bug67693.phpt

+2-2
Original file line numberDiff line numberDiff line change
@@ -16,9 +16,9 @@ echo"\nDone";
1616
?>
1717
--EXPECT--
1818
array(2) {
19-
[0]=>
19+
[-1]=>
2020
int(0)
21-
[1]=>
21+
[0]=>
2222
int(0)
2323
}
2424

Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
--TEST--
2+
Test arrays starting with negative indices
3+
--FILE--
4+
<?php
5+
6+
$a = array_fill(-2, 3, true);
7+
$b = [-2 => true, true, true];
8+
$c = ["string" => true, -2 => true, true, true];
9+
unset($c["string"]);
10+
$d[-2] = true;
11+
$d[] = true;
12+
$d[] = true;
13+
14+
var_dump($a === $b && $b === $c && $c === $d);
15+
var_dump($a);
16+
?>
17+
--EXPECT--
18+
bool(true)
19+
array(3) {
20+
[-2]=>
21+
bool(true)
22+
[-1]=>
23+
bool(true)
24+
[0]=>
25+
bool(true)
26+
}

0 commit comments

Comments
 (0)