Skip to content

Commit 14830ab

Browse files
committed
Merge branch 'PHP-8.0'
* PHP-8.0: Detect self-addition of array more accurately Deindirect source elements in zend_hash_merge
2 parents ed3f197 + 66ecee6 commit 14830ab

File tree

4 files changed

+44
-14
lines changed

4 files changed

+44
-14
lines changed

Zend/tests/array_add_indirect.phpt

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
--TEST--
2+
Array addition should not add INDIRECT elements
3+
--FILE--
4+
<?php
5+
6+
$x = 1;
7+
$ary = ['y' => 1];
8+
$ary += $GLOBALS;
9+
var_dump($ary['x']);
10+
$x = 2;
11+
var_dump($ary['x']);
12+
13+
?>
14+
--EXPECT--
15+
int(1)
16+
int(1)
Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
--TEST--
2+
Add $GLOBALS to itself
3+
--FILE--
4+
<?php
5+
$GLOBALS += $GLOBALS;
6+
$x = $GLOBALS + $GLOBALS;
7+
?>
8+
===DONE===
9+
--EXPECT--
10+
===DONE===

Zend/zend_hash.c

Lines changed: 17 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -2149,7 +2149,7 @@ ZEND_API void ZEND_FASTCALL zend_hash_merge(HashTable *target, HashTable *source
21492149
{
21502150
uint32_t idx;
21512151
Bucket *p;
2152-
zval *t;
2152+
zval *t, *s;
21532153

21542154
IS_CONSISTENT(source);
21552155
IS_CONSISTENT(target);
@@ -2158,18 +2158,20 @@ ZEND_API void ZEND_FASTCALL zend_hash_merge(HashTable *target, HashTable *source
21582158
if (overwrite) {
21592159
for (idx = 0; idx < source->nNumUsed; idx++) {
21602160
p = source->arData + idx;
2161-
if (UNEXPECTED(Z_TYPE(p->val) == IS_UNDEF)) continue;
2162-
if (UNEXPECTED(Z_TYPE(p->val) == IS_INDIRECT) &&
2163-
UNEXPECTED(Z_TYPE_P(Z_INDIRECT(p->val)) == IS_UNDEF)) {
2164-
continue;
2161+
s = &p->val;
2162+
if (UNEXPECTED(Z_TYPE_P(s) == IS_INDIRECT)) {
2163+
s = Z_INDIRECT_P(s);
2164+
}
2165+
if (UNEXPECTED(Z_TYPE_P(s) == IS_UNDEF)) {
2166+
continue;
21652167
}
21662168
if (p->key) {
2167-
t = _zend_hash_add_or_update_i(target, p->key, &p->val, HASH_UPDATE | HASH_UPDATE_INDIRECT);
2169+
t = _zend_hash_add_or_update_i(target, p->key, s, HASH_UPDATE | HASH_UPDATE_INDIRECT);
21682170
if (pCopyConstructor) {
21692171
pCopyConstructor(t);
21702172
}
21712173
} else {
2172-
t = zend_hash_index_update(target, p->h, &p->val);
2174+
t = zend_hash_index_update(target, p->h, s);
21732175
if (pCopyConstructor) {
21742176
pCopyConstructor(t);
21752177
}
@@ -2178,18 +2180,20 @@ ZEND_API void ZEND_FASTCALL zend_hash_merge(HashTable *target, HashTable *source
21782180
} else {
21792181
for (idx = 0; idx < source->nNumUsed; idx++) {
21802182
p = source->arData + idx;
2181-
if (UNEXPECTED(Z_TYPE(p->val) == IS_UNDEF)) continue;
2182-
if (UNEXPECTED(Z_TYPE(p->val) == IS_INDIRECT) &&
2183-
UNEXPECTED(Z_TYPE_P(Z_INDIRECT(p->val)) == IS_UNDEF)) {
2184-
continue;
2183+
s = &p->val;
2184+
if (UNEXPECTED(Z_TYPE_P(s) == IS_INDIRECT)) {
2185+
s = Z_INDIRECT_P(s);
2186+
}
2187+
if (UNEXPECTED(Z_TYPE_P(s) == IS_UNDEF)) {
2188+
continue;
21852189
}
21862190
if (p->key) {
2187-
t = _zend_hash_add_or_update_i(target, p->key, &p->val, HASH_ADD | HASH_UPDATE_INDIRECT);
2191+
t = _zend_hash_add_or_update_i(target, p->key, s, HASH_ADD | HASH_UPDATE_INDIRECT);
21882192
if (t && pCopyConstructor) {
21892193
pCopyConstructor(t);
21902194
}
21912195
} else {
2192-
t = zend_hash_index_add(target, p->h, &p->val);
2196+
t = zend_hash_index_add(target, p->h, s);
21932197
if (t && pCopyConstructor) {
21942198
pCopyConstructor(t);
21952199
}

Zend/zend_operators.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -950,7 +950,7 @@ static ZEND_COLD zend_never_inline void ZEND_FASTCALL zend_binop_error(const cha
950950

951951
static zend_never_inline void ZEND_FASTCALL add_function_array(zval *result, zval *op1, zval *op2) /* {{{ */
952952
{
953-
if ((result == op1) && (result == op2)) {
953+
if (result == op1 && Z_ARR_P(op1) == Z_ARR_P(op2)) {
954954
/* $a += $a */
955955
return;
956956
}

0 commit comments

Comments
 (0)