Skip to content

Commit 0a654fd

Browse files
committed
Reduce HT_MAX_SIZE to account for the max load factor of 0.5
zend_hash allocates a hash table twice as big as nTableSize (HT_HASH_SIZE(HT_SIZE_TO_MASK(nTableSize)) == nTableSize*2), so HT_MAX_SIZE must be half the max table size or less.
1 parent 3152b7b commit 0a654fd

File tree

2 files changed

+12
-2
lines changed

2 files changed

+12
-2
lines changed

Zend/zend_hash.c

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -166,6 +166,8 @@ static zend_always_inline void zend_hash_real_init_mixed_ex(HashTable *ht)
166166
void *data;
167167
uint32_t nSize = ht->nTableSize;
168168

169+
ZEND_ASSERT(HT_SIZE_TO_MASK(nSize));
170+
169171
if (UNEXPECTED(GC_FLAGS(ht) & IS_ARRAY_PERSISTENT)) {
170172
data = pemalloc(HT_SIZE_EX(nSize, HT_SIZE_TO_MASK(nSize)), 1);
171173
} else if (EXPECTED(nSize == HT_MIN_SIZE)) {
@@ -341,6 +343,8 @@ ZEND_API void ZEND_FASTCALL zend_hash_packed_to_hash(HashTable *ht)
341343
Bucket *old_buckets = ht->arData;
342344
uint32_t nSize = ht->nTableSize;
343345

346+
ZEND_ASSERT(HT_SIZE_TO_MASK(nSize));
347+
344348
HT_ASSERT_RC1(ht);
345349
HT_FLAGS(ht) &= ~HASH_FLAG_PACKED;
346350
new_data = pemalloc(HT_SIZE_EX(nSize, HT_SIZE_TO_MASK(nSize)), GC_FLAGS(ht) & IS_ARRAY_PERSISTENT);
@@ -369,7 +373,11 @@ ZEND_API void ZEND_FASTCALL zend_hash_to_packed(HashTable *ht)
369373
ZEND_API void ZEND_FASTCALL zend_hash_extend(HashTable *ht, uint32_t nSize, bool packed)
370374
{
371375
HT_ASSERT_RC1(ht);
376+
372377
if (nSize == 0) return;
378+
379+
ZEND_ASSERT(HT_SIZE_TO_MASK(nSize));
380+
373381
if (UNEXPECTED(HT_FLAGS(ht) & HASH_FLAG_UNINITIALIZED)) {
374382
if (nSize > ht->nTableSize) {
375383
ht->nTableSize = zend_hash_check_size(nSize);
@@ -1207,6 +1215,8 @@ static void ZEND_FASTCALL zend_hash_do_resize(HashTable *ht)
12071215
uint32_t nSize = ht->nTableSize + ht->nTableSize;
12081216
Bucket *old_buckets = ht->arData;
12091217

1218+
ZEND_ASSERT(HT_SIZE_TO_MASK(nSize));
1219+
12101220
ht->nTableSize = nSize;
12111221
new_data = pemalloc(HT_SIZE_EX(nSize, HT_SIZE_TO_MASK(nSize)), GC_FLAGS(ht) & IS_ARRAY_PERSISTENT);
12121222
ht->nTableMask = HT_SIZE_TO_MASK(ht->nTableSize);

Zend/zend_types.h

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -401,15 +401,15 @@ struct _zend_array {
401401
#define HT_MIN_SIZE 8
402402

403403
#if SIZEOF_SIZE_T == 4
404-
# define HT_MAX_SIZE 0x04000000 /* small enough to avoid overflow checks */
404+
# define HT_MAX_SIZE 0x02000000 /* small enough to avoid overflow checks */
405405
# define HT_HASH_TO_BUCKET_EX(data, idx) \
406406
((Bucket*)((char*)(data) + (idx)))
407407
# define HT_IDX_TO_HASH(idx) \
408408
((idx) * sizeof(Bucket))
409409
# define HT_HASH_TO_IDX(idx) \
410410
((idx) / sizeof(Bucket))
411411
#elif SIZEOF_SIZE_T == 8
412-
# define HT_MAX_SIZE 0x80000000
412+
# define HT_MAX_SIZE 0x40000000
413413
# define HT_HASH_TO_BUCKET_EX(data, idx) \
414414
((data) + (idx))
415415
# define HT_IDX_TO_HASH(idx) \

0 commit comments

Comments
 (0)