Skip to content

Commit a2f8a76

Browse files
committed
Prevent HashTable compaction below HT_MIN_SIZE (this may lead to hash collisions).
1 parent 9c35f87 commit a2f8a76

File tree

2 files changed

+18
-14
lines changed

2 files changed

+18
-14
lines changed

ext/opcache/zend_persist.c

Lines changed: 16 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -94,13 +94,15 @@ static void zend_hash_persist(HashTable *ht, zend_persist_func_t pPersistElement
9494
/* compact table */
9595
void *old_data = HT_GET_DATA_ADDR(ht);
9696
Bucket *old_buckets = ht->arData;
97-
int32_t hash_size = -(int32_t)ht->nTableMask;
97+
int32_t hash_size;
9898

99-
while (hash_size >> 1 > ht->nNumUsed) {
100-
hash_size >>= 1;
101-
}
102-
if (hash_size < -HT_MIN_MASK) {
103-
hash_size = -HT_MIN_MASK;
99+
if (ht->nNumUsed <= HT_MIN_SIZE) {
100+
hash_size = HT_MIN_SIZE;
101+
} else {
102+
hash_size = -(int32_t)ht->nTableMask;
103+
while (hash_size >> 1 > ht->nNumUsed) {
104+
hash_size >>= 1;
105+
}
104106
}
105107
ht->nTableMask = -hash_size;
106108
ZEND_ASSERT(((zend_uintptr_t)ZCG(mem) & 0x7) == 0); /* should be 8 byte aligned */
@@ -174,13 +176,15 @@ static void zend_hash_persist_immutable(HashTable *ht)
174176
/* compact table */
175177
void *old_data = HT_GET_DATA_ADDR(ht);
176178
Bucket *old_buckets = ht->arData;
177-
int32_t hash_size = -(int32_t)ht->nTableMask;
179+
int32_t hash_size;
178180

179-
while (hash_size >> 1 > ht->nNumUsed) {
180-
hash_size >>= 1;
181-
}
182-
if (hash_size < -HT_MIN_MASK) {
183-
hash_size = -HT_MIN_MASK;
181+
if (ht->nNumUsed <= HT_MIN_SIZE) {
182+
hash_size = HT_MIN_SIZE;
183+
} else {
184+
hash_size = -(int32_t)ht->nTableMask;
185+
while (hash_size >> 1 > ht->nNumUsed) {
186+
hash_size >>= 1;
187+
}
184188
}
185189
ht->nTableMask = -hash_size;
186190
ZEND_ASSERT(((zend_uintptr_t)ZCG(mem) & 0x7) == 0); /* should be 8 byte aligned */

ext/opcache/zend_persist_calc.c

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -65,8 +65,8 @@ static void zend_hash_persist_calc(HashTable *ht, void (*pPersistElement)(zval *
6565
while (hash_size >> 1 > ht->nNumUsed) {
6666
hash_size >>= 1;
6767
}
68-
if (hash_size < -HT_MIN_MASK) {
69-
hash_size = -HT_MIN_MASK;
68+
if (hash_size < HT_MIN_SIZE) {
69+
hash_size = HT_MIN_SIZE;
7070
}
7171
ADD_SIZE(hash_size * sizeof(uint32_t) + ht->nNumUsed * sizeof(Bucket));
7272
} else {

0 commit comments

Comments
 (0)