summaryrefslogtreecommitdiff
path: root/Zend
diff options
context:
space:
mode:
authorNikita Popov <nikita.ppv@gmail.com>2020-10-12 11:24:59 +0200
committerNikita Popov <nikita.ppv@gmail.com>2020-10-12 11:24:59 +0200
commit5a7f9afb9902c45218a0fff9112d34e05be7b61c (patch)
tree7263f88ef62ea504644f5695276352a005173b84 /Zend
parent9a2e5cfccb3431614c84bfa1f4e1d66370698b6d (diff)
parent3c4dd73c023e4aea317f774e045fdccc644f24b5 (diff)
downloadphp-git-5a7f9afb9902c45218a0fff9112d34e05be7b61c.tar.gz
Merge branch 'PHP-7.3' into PHP-7.4
* PHP-7.3: Detect self-addition of array more accurately Deindirect source elements in zend_hash_merge
Diffstat (limited to 'Zend')
-rw-r--r--Zend/tests/array_add_indirect.phpt16
-rw-r--r--Zend/tests/array_self_add_globals.phpt10
-rw-r--r--Zend/zend_hash.c30
-rw-r--r--Zend/zend_operators.c2
4 files changed, 44 insertions, 14 deletions
diff --git a/Zend/tests/array_add_indirect.phpt b/Zend/tests/array_add_indirect.phpt
new file mode 100644
index 0000000000..821cc475b9
--- /dev/null
+++ b/Zend/tests/array_add_indirect.phpt
@@ -0,0 +1,16 @@
+--TEST--
+Array addition should not add INDIRECT elements
+--FILE--
+<?php
+
+$x = 1;
+$ary = ['y' => 1];
+$ary += $GLOBALS;
+var_dump($ary['x']);
+$x = 2;
+var_dump($ary['x']);
+
+?>
+--EXPECT--
+int(1)
+int(1)
diff --git a/Zend/tests/array_self_add_globals.phpt b/Zend/tests/array_self_add_globals.phpt
new file mode 100644
index 0000000000..ebad7c3fdf
--- /dev/null
+++ b/Zend/tests/array_self_add_globals.phpt
@@ -0,0 +1,10 @@
+--TEST--
+Add $GLOBALS to itself
+--FILE--
+<?php
+$GLOBALS += $GLOBALS;
+$x = $GLOBALS + $GLOBALS;
+?>
+===DONE===
+--EXPECT--
+===DONE===
diff --git a/Zend/zend_hash.c b/Zend/zend_hash.c
index 4fd0c549b5..d35d8afd53 100644
--- a/Zend/zend_hash.c
+++ b/Zend/zend_hash.c
@@ -2124,7 +2124,7 @@ ZEND_API void ZEND_FASTCALL zend_hash_merge(HashTable *target, HashTable *source
{
uint32_t idx;
Bucket *p;
- zval *t;
+ zval *t, *s;
IS_CONSISTENT(source);
IS_CONSISTENT(target);
@@ -2133,18 +2133,20 @@ ZEND_API void ZEND_FASTCALL zend_hash_merge(HashTable *target, HashTable *source
if (overwrite) {
for (idx = 0; idx < source->nNumUsed; idx++) {
p = source->arData + idx;
- if (UNEXPECTED(Z_TYPE(p->val) == IS_UNDEF)) continue;
- if (UNEXPECTED(Z_TYPE(p->val) == IS_INDIRECT) &&
- UNEXPECTED(Z_TYPE_P(Z_INDIRECT(p->val)) == IS_UNDEF)) {
- continue;
+ s = &p->val;
+ if (UNEXPECTED(Z_TYPE_P(s) == IS_INDIRECT)) {
+ s = Z_INDIRECT_P(s);
+ }
+ if (UNEXPECTED(Z_TYPE_P(s) == IS_UNDEF)) {
+ continue;
}
if (p->key) {
- t = _zend_hash_add_or_update_i(target, p->key, &p->val, HASH_UPDATE | HASH_UPDATE_INDIRECT);
+ t = _zend_hash_add_or_update_i(target, p->key, s, HASH_UPDATE | HASH_UPDATE_INDIRECT);
if (pCopyConstructor) {
pCopyConstructor(t);
}
} else {
- t = zend_hash_index_update(target, p->h, &p->val);
+ t = zend_hash_index_update(target, p->h, s);
if (pCopyConstructor) {
pCopyConstructor(t);
}
@@ -2153,18 +2155,20 @@ ZEND_API void ZEND_FASTCALL zend_hash_merge(HashTable *target, HashTable *source
} else {
for (idx = 0; idx < source->nNumUsed; idx++) {
p = source->arData + idx;
- if (UNEXPECTED(Z_TYPE(p->val) == IS_UNDEF)) continue;
- if (UNEXPECTED(Z_TYPE(p->val) == IS_INDIRECT) &&
- UNEXPECTED(Z_TYPE_P(Z_INDIRECT(p->val)) == IS_UNDEF)) {
- continue;
+ s = &p->val;
+ if (UNEXPECTED(Z_TYPE_P(s) == IS_INDIRECT)) {
+ s = Z_INDIRECT_P(s);
+ }
+ if (UNEXPECTED(Z_TYPE_P(s) == IS_UNDEF)) {
+ continue;
}
if (p->key) {
- t = _zend_hash_add_or_update_i(target, p->key, &p->val, HASH_ADD | HASH_UPDATE_INDIRECT);
+ t = _zend_hash_add_or_update_i(target, p->key, s, HASH_ADD | HASH_UPDATE_INDIRECT);
if (t && pCopyConstructor) {
pCopyConstructor(t);
}
} else {
- t = zend_hash_index_add(target, p->h, &p->val);
+ t = zend_hash_index_add(target, p->h, s);
if (t && pCopyConstructor) {
pCopyConstructor(t);
}
diff --git a/Zend/zend_operators.c b/Zend/zend_operators.c
index 08fc18f261..596581270b 100644
--- a/Zend/zend_operators.c
+++ b/Zend/zend_operators.c
@@ -934,7 +934,7 @@ ZEND_API zend_string* ZEND_FASTCALL zval_try_get_string_func(zval *op) /* {{{ */
static zend_never_inline void ZEND_FASTCALL add_function_array(zval *result, zval *op1, zval *op2) /* {{{ */
{
- if ((result == op1) && (result == op2)) {
+ if (result == op1 && Z_ARR_P(op1) == Z_ARR_P(op2)) {
/* $a += $a */
return;
}