diff options
author | Dmitry Stogov <dmitry@zend.com> | 2016-03-02 15:09:50 +0300 |
---|---|---|
committer | Dmitry Stogov <dmitry@zend.com> | 2016-03-02 15:09:50 +0300 |
commit | 701edb8c82439ed5986be0718a5246cd37452f96 (patch) | |
tree | bc03cf2a50faec308c33c2b7db6445abb66e5bd7 | |
parent | 95eda16fe97aa6c3647f8624fe2345f3c571f0c2 (diff) | |
parent | b6bbe33f0555a9f5a2085b1716659a94232fe0da (diff) | |
download | php-git-701edb8c82439ed5986be0718a5246cd37452f96.tar.gz |
Merge branch 'PHP-7.0'
* PHP-7.0:
Better fix for IS_INDIRECT support in zend_hash_merge()
-rw-r--r-- | Zend/zend_hash.c | 72 |
1 files changed, 48 insertions, 24 deletions
diff --git a/Zend/zend_hash.c b/Zend/zend_hash.c index 1ffaff0361..39e9e14024 100644 --- a/Zend/zend_hash.c +++ b/Zend/zend_hash.c @@ -571,12 +571,25 @@ static zend_always_inline zval *_zend_hash_add_or_update_i(HashTable *ht, zend_s zval *data; if (flag & HASH_ADD) { - return NULL; - } - ZEND_ASSERT(&p->val != pData); - data = &p->val; - if ((flag & HASH_UPDATE_INDIRECT) && Z_TYPE_P(data) == IS_INDIRECT) { - data = Z_INDIRECT_P(data); + if (!(flag & HASH_UPDATE_INDIRECT)) { + return NULL; + } + ZEND_ASSERT(&p->val != pData); + data = &p->val; + if (Z_TYPE_P(data) == IS_INDIRECT) { + data = Z_INDIRECT_P(data); + if (Z_TYPE_P(data) != IS_UNDEF) { + return NULL; + } + } else { + return NULL; + } + } else { + ZEND_ASSERT(&p->val != pData); + data = &p->val; + if ((flag & HASH_UPDATE_INDIRECT) && Z_TYPE_P(data) == IS_INDIRECT) { + data = Z_INDIRECT_P(data); + } } HANDLE_BLOCK_INTERRUPTIONS(); if (ht->pDestructor) { @@ -1869,31 +1882,42 @@ ZEND_API void ZEND_FASTCALL _zend_hash_merge(HashTable *target, HashTable *sourc IS_CONSISTENT(target); HT_ASSERT(GC_REFCOUNT(target) == 1); - for (idx = 0; idx < source->nNumUsed; idx++) { - p = source->arData + idx; - if (UNEXPECTED(Z_TYPE(p->val) == IS_UNDEF)) continue; - if (p->key) { - if (EXPECTED((t = zend_hash_find_ind(target, p->key)) == NULL)) { - t = zend_hash_update_ind(target, p->key, &p->val); + 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; + } + if (p->key) { + t = _zend_hash_add_or_update_i(target, p->key, &p->val, HASH_UPDATE | HASH_UPDATE_INDIRECT ZEND_FILE_LINE_RELAY_CC); if (t && pCopyConstructor) { pCopyConstructor(t); } } else { - if (!overwrite) { - continue; - } - if (target->pDestructor) { - target->pDestructor(t); - } - ZVAL_COPY_VALUE(t, &p->val); - if (pCopyConstructor) { + t = zend_hash_index_update(target, p->h, &p->val); + if (t && pCopyConstructor) { pCopyConstructor(t); } } - } else { - if ((overwrite || !zend_hash_index_exists(target, p->h))) { - t = zend_hash_index_update(target, p->h, &p->val); - if (t && pCopyConstructor) { + } + } 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; + } + if (p->key) { + t = _zend_hash_add_or_update_i(target, p->key, &p->val, HASH_ADD | HASH_UPDATE_INDIRECT ZEND_FILE_LINE_RELAY_CC); + if (t && pCopyConstructor) { + pCopyConstructor(t); + } + } else { + t = zend_hash_index_add(target, p->h, &p->val); + if (t && pCopyConstructor) { pCopyConstructor(t); } } |