From 437e91e194c9a0dc91880dd5a15f7df6b86a363c Mon Sep 17 00:00:00 2001 From: Dmitry Stogov Date: Tue, 4 Sep 2018 01:19:07 +0300 Subject: [PATCH] Keep collision list ordered from higher to lower buckets. --- Zend/zend_hash.c | 22 +++++++++++++++++++--- 1 file changed, 19 insertions(+), 3 deletions(-) diff --git a/Zend/zend_hash.c b/Zend/zend_hash.c index 0caf37d7aaa..7ef0db619d1 100644 --- a/Zend/zend_hash.c +++ b/Zend/zend_hash.c @@ -339,6 +339,11 @@ ZEND_API void ZEND_FASTCALL zend_hash_discard(HashTable *ht, uint32_t nNumUsed) if (UNEXPECTED(Z_TYPE(p->val) == IS_UNDEF)) continue; ht->nNumOfElements--; /* Collision pointers always directed from higher to lower buckets */ +#if 0 + if (!(Z_NEXT(p->val) == HT_INVALID_IDX || HT_HASH_TO_BUCKET_EX(arData, Z_NEXT(p->val)) < p)) { + abort(); + } +#endif nIndex = p->h | ht->nTableMask; HT_HASH_EX(arData, nIndex) = Z_NEXT(p->val); } @@ -1069,9 +1074,20 @@ ZEND_API zval* ZEND_FASTCALL zend_hash_set_bucket_key(HashTable *ht, Bucket *b, b->key = key; b->h = ZSTR_H(key); nIndex = b->h | ht->nTableMask; - Z_NEXT(b->val) = HT_HASH_EX(arData, nIndex); - HT_HASH_EX(arData, nIndex) = HT_IDX_TO_HASH(idx); - + idx = HT_IDX_TO_HASH(idx); + i = HT_HASH_EX(arData, nIndex); + if (i == HT_INVALID_IDX || i < idx) { + Z_NEXT(b->val) = i; + HT_HASH_EX(arData, nIndex) = idx; + } else { + p = HT_HASH_TO_BUCKET_EX(arData, i); + while (Z_NEXT(p->val) != HT_INVALID_IDX && Z_NEXT(p->val) > idx) { + i = Z_NEXT(p->val); + p = HT_HASH_TO_BUCKET_EX(arData, i); + } + Z_NEXT(b->val) = Z_NEXT(p->val); + Z_NEXT(p->val) = idx; + } return &b->val; }