Skip to content

Commit 23e1e12

Browse files
committed
Clean up zend_hash_compare implementation
Split off zend_hash_compare_impl into separate function that does not bother with recursion protection. We had two cases where UNPROTECT_RECURSION was missing.
1 parent e8217a2 commit 23e1e12

File tree

1 file changed

+26
-42
lines changed

1 file changed

+26
-42
lines changed

Zend/zend_hash.c

Lines changed: 26 additions & 42 deletions
Original file line numberDiff line numberDiff line change
@@ -2206,91 +2206,67 @@ ZEND_API int ZEND_FASTCALL zend_hash_sort_ex(HashTable *ht, sort_func_t sort, co
22062206
return SUCCESS;
22072207
}
22082208

2209-
2210-
ZEND_API int zend_hash_compare(HashTable *ht1, HashTable *ht2, compare_func_t compar, zend_bool ordered)
2211-
{
2209+
static zend_always_inline int zend_hash_compare_impl(HashTable *ht1, HashTable *ht2, compare_func_t compar, zend_bool ordered) {
22122210
uint32_t idx1, idx2;
2213-
Bucket *p1, *p2 = NULL;
2214-
int result;
2215-
zval *pData1, *pData2;
2216-
2217-
IS_CONSISTENT(ht1);
2218-
IS_CONSISTENT(ht2);
2219-
2220-
HASH_PROTECT_RECURSION(ht1);
2221-
HASH_PROTECT_RECURSION(ht2);
22222211

22232212
if (ht1->nNumOfElements != ht2->nNumOfElements) {
2224-
HASH_UNPROTECT_RECURSION(ht1);
2225-
HASH_UNPROTECT_RECURSION(ht2);
22262213
return ht1->nNumOfElements > ht2->nNumOfElements ? 1 : -1;
22272214
}
22282215

22292216
for (idx1 = 0, idx2 = 0; idx1 < ht1->nNumUsed; idx1++) {
2230-
p1 = ht1->arData + idx1;
2231-
if (Z_TYPE(p1->val) == IS_UNDEF) continue;
2217+
Bucket *p1 = ht1->arData + idx1, *p2;
2218+
zval *pData1, *pData2;
2219+
int result;
22322220

2221+
if (Z_TYPE(p1->val) == IS_UNDEF) continue;
22332222
if (ordered) {
22342223
while (1) {
2224+
ZEND_ASSERT(idx2 != ht2->nNumUsed);
22352225
p2 = ht2->arData + idx2;
2236-
if (idx2 == ht2->nNumUsed) {
2237-
HASH_UNPROTECT_RECURSION(ht1);
2238-
HASH_UNPROTECT_RECURSION(ht2);
2239-
return 1; /* That's not supposed to happen */
2240-
}
22412226
if (Z_TYPE(p2->val) != IS_UNDEF) break;
22422227
idx2++;
22432228
}
22442229
if (p1->key == NULL && p2->key == NULL) { /* numeric indices */
22452230
if (p1->h != p2->h) {
2246-
HASH_UNPROTECT_RECURSION(ht1);
2247-
HASH_UNPROTECT_RECURSION(ht2);
22482231
return p1->h > p2->h ? 1 : -1;
22492232
}
22502233
} else if (p1->key != NULL && p2->key != NULL) { /* string indices */
22512234
if (p1->key->len != p2->key->len) {
2252-
HASH_UNPROTECT_RECURSION(ht1);
2253-
HASH_UNPROTECT_RECURSION(ht2);
22542235
return p1->key->len > p2->key->len ? 1 : -1;
22552236
}
22562237

22572238
result = memcmp(p1->key->val, p2->key->val, p1->key->len);
22582239
if (result != 0) {
2259-
HASH_UNPROTECT_RECURSION(ht1);
2260-
HASH_UNPROTECT_RECURSION(ht2);
22612240
return result;
22622241
}
22632242
} else {
22642243
/* Mixed key types: A string key is considered as larger */
2265-
HASH_UNPROTECT_RECURSION(ht1);
2266-
HASH_UNPROTECT_RECURSION(ht2);
22672244
return p1->key != NULL ? 1 : -1;
22682245
}
22692246
pData2 = &p2->val;
2247+
idx2++;
22702248
} else {
22712249
if (p1->key == NULL) { /* numeric index */
22722250
pData2 = zend_hash_index_find(ht2, p1->h);
22732251
if (pData2 == NULL) {
2274-
HASH_UNPROTECT_RECURSION(ht1);
2275-
HASH_UNPROTECT_RECURSION(ht2);
22762252
return 1;
22772253
}
22782254
} else { /* string index */
22792255
pData2 = zend_hash_find(ht2, p1->key);
22802256
if (pData2 == NULL) {
2281-
HASH_UNPROTECT_RECURSION(ht1);
2282-
HASH_UNPROTECT_RECURSION(ht2);
22832257
return 1;
22842258
}
22852259
}
22862260
}
2261+
22872262
pData1 = &p1->val;
22882263
if (Z_TYPE_P(pData1) == IS_INDIRECT) {
22892264
pData1 = Z_INDIRECT_P(pData1);
22902265
}
22912266
if (Z_TYPE_P(pData2) == IS_INDIRECT) {
22922267
pData2 = Z_INDIRECT_P(pData2);
22932268
}
2269+
22942270
if (Z_TYPE_P(pData1) == IS_UNDEF) {
22952271
if (Z_TYPE_P(pData2) != IS_UNDEF) {
22962272
return -1;
@@ -2299,20 +2275,28 @@ ZEND_API int zend_hash_compare(HashTable *ht1, HashTable *ht2, compare_func_t co
22992275
return 1;
23002276
} else {
23012277
result = compar(pData1, pData2);
2302-
}
2303-
if (result != 0) {
2304-
HASH_UNPROTECT_RECURSION(ht1);
2305-
HASH_UNPROTECT_RECURSION(ht2);
2306-
return result;
2307-
}
2308-
if (ordered) {
2309-
idx2++;
2278+
if (result != 0) {
2279+
return result;
2280+
}
23102281
}
23112282
}
23122283

2284+
return 0;
2285+
}
2286+
2287+
ZEND_API int zend_hash_compare(HashTable *ht1, HashTable *ht2, compare_func_t compar, zend_bool ordered)
2288+
{
2289+
int result;
2290+
IS_CONSISTENT(ht1);
2291+
IS_CONSISTENT(ht2);
2292+
2293+
HASH_PROTECT_RECURSION(ht1);
2294+
HASH_PROTECT_RECURSION(ht2);
2295+
result = zend_hash_compare_impl(ht1, ht2, compar, ordered);
23132296
HASH_UNPROTECT_RECURSION(ht1);
23142297
HASH_UNPROTECT_RECURSION(ht2);
2315-
return 0;
2298+
2299+
return result;
23162300
}
23172301

23182302

0 commit comments

Comments
 (0)