Skip to content

Commit b6bbe33

Browse files
committed
Better fix for IS_INDIRECT support in zend_hash_merge()
1 parent afedd4f commit b6bbe33

File tree

1 file changed

+48
-24
lines changed

1 file changed

+48
-24
lines changed

Zend/zend_hash.c

Lines changed: 48 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -571,12 +571,25 @@ static zend_always_inline zval *_zend_hash_add_or_update_i(HashTable *ht, zend_s
571571
zval *data;
572572

573573
if (flag & HASH_ADD) {
574-
return NULL;
575-
}
576-
ZEND_ASSERT(&p->val != pData);
577-
data = &p->val;
578-
if ((flag & HASH_UPDATE_INDIRECT) && Z_TYPE_P(data) == IS_INDIRECT) {
579-
data = Z_INDIRECT_P(data);
574+
if (!(flag & HASH_UPDATE_INDIRECT)) {
575+
return NULL;
576+
}
577+
ZEND_ASSERT(&p->val != pData);
578+
data = &p->val;
579+
if (Z_TYPE_P(data) == IS_INDIRECT) {
580+
data = Z_INDIRECT_P(data);
581+
if (Z_TYPE_P(data) != IS_UNDEF) {
582+
return NULL;
583+
}
584+
} else {
585+
return NULL;
586+
}
587+
} else {
588+
ZEND_ASSERT(&p->val != pData);
589+
data = &p->val;
590+
if ((flag & HASH_UPDATE_INDIRECT) && Z_TYPE_P(data) == IS_INDIRECT) {
591+
data = Z_INDIRECT_P(data);
592+
}
580593
}
581594
HANDLE_BLOCK_INTERRUPTIONS();
582595
if (ht->pDestructor) {
@@ -1869,31 +1882,42 @@ ZEND_API void ZEND_FASTCALL _zend_hash_merge(HashTable *target, HashTable *sourc
18691882
IS_CONSISTENT(target);
18701883
HT_ASSERT(GC_REFCOUNT(target) == 1);
18711884

1872-
for (idx = 0; idx < source->nNumUsed; idx++) {
1873-
p = source->arData + idx;
1874-
if (UNEXPECTED(Z_TYPE(p->val) == IS_UNDEF)) continue;
1875-
if (p->key) {
1876-
if (EXPECTED((t = zend_hash_find_ind(target, p->key)) == NULL)) {
1877-
t = zend_hash_update_ind(target, p->key, &p->val);
1885+
if (overwrite) {
1886+
for (idx = 0; idx < source->nNumUsed; idx++) {
1887+
p = source->arData + idx;
1888+
if (UNEXPECTED(Z_TYPE(p->val) == IS_UNDEF)) continue;
1889+
if (UNEXPECTED(Z_TYPE(p->val) == IS_INDIRECT) &&
1890+
UNEXPECTED(Z_TYPE_P(Z_INDIRECT(p->val)) == IS_UNDEF)) {
1891+
continue;
1892+
}
1893+
if (p->key) {
1894+
t = _zend_hash_add_or_update_i(target, p->key, &p->val, HASH_UPDATE | HASH_UPDATE_INDIRECT ZEND_FILE_LINE_RELAY_CC);
18781895
if (t && pCopyConstructor) {
18791896
pCopyConstructor(t);
18801897
}
18811898
} else {
1882-
if (!overwrite) {
1883-
continue;
1884-
}
1885-
if (target->pDestructor) {
1886-
target->pDestructor(t);
1887-
}
1888-
ZVAL_COPY_VALUE(t, &p->val);
1889-
if (pCopyConstructor) {
1899+
t = zend_hash_index_update(target, p->h, &p->val);
1900+
if (t && pCopyConstructor) {
18901901
pCopyConstructor(t);
18911902
}
18921903
}
1893-
} else {
1894-
if ((overwrite || !zend_hash_index_exists(target, p->h))) {
1895-
t = zend_hash_index_update(target, p->h, &p->val);
1896-
if (t && pCopyConstructor) {
1904+
}
1905+
} else {
1906+
for (idx = 0; idx < source->nNumUsed; idx++) {
1907+
p = source->arData + idx;
1908+
if (UNEXPECTED(Z_TYPE(p->val) == IS_UNDEF)) continue;
1909+
if (UNEXPECTED(Z_TYPE(p->val) == IS_INDIRECT) &&
1910+
UNEXPECTED(Z_TYPE_P(Z_INDIRECT(p->val)) == IS_UNDEF)) {
1911+
continue;
1912+
}
1913+
if (p->key) {
1914+
t = _zend_hash_add_or_update_i(target, p->key, &p->val, HASH_ADD | HASH_UPDATE_INDIRECT ZEND_FILE_LINE_RELAY_CC);
1915+
if (t && pCopyConstructor) {
1916+
pCopyConstructor(t);
1917+
}
1918+
} else {
1919+
t = zend_hash_index_add(target, p->h, &p->val);
1920+
if (t && pCopyConstructor) {
18971921
pCopyConstructor(t);
18981922
}
18991923
}

0 commit comments

Comments
 (0)