@@ -309,8 +309,9 @@ ZEND_API void ZEND_FASTCALL zend_hash_packed_grow(HashTable *ht)
309
309
if (ht -> nTableSize >= HT_MAX_SIZE ) {
310
310
zend_error_noreturn (E_ERROR , "Possible integer overflow in memory allocation (%u * %zu + %zu)" , ht -> nTableSize * 2 , sizeof (Bucket ), sizeof (Bucket ));
311
311
}
312
- ht -> nTableSize += ht -> nTableSize ;
313
- HT_SET_DATA_ADDR (ht , perealloc2 (HT_GET_DATA_ADDR (ht ), HT_SIZE_EX (ht -> nTableSize , HT_MIN_MASK ), HT_USED_SIZE (ht ), GC_FLAGS (ht ) & IS_ARRAY_PERSISTENT ));
312
+ uint32_t newTableSize = ht -> nTableSize * 2 ;
313
+ HT_SET_DATA_ADDR (ht , perealloc2 (HT_GET_DATA_ADDR (ht ), HT_SIZE_EX (newTableSize , HT_MIN_MASK ), HT_USED_SIZE (ht ), GC_FLAGS (ht ) & IS_ARRAY_PERSISTENT ));
314
+ ht -> nTableSize = newTableSize ;
314
315
}
315
316
316
317
ZEND_API void ZEND_FASTCALL zend_hash_real_init (HashTable * ht , bool packed )
@@ -346,8 +347,9 @@ ZEND_API void ZEND_FASTCALL zend_hash_packed_to_hash(HashTable *ht)
346
347
ZEND_ASSERT (HT_SIZE_TO_MASK (nSize ));
347
348
348
349
HT_ASSERT_RC1 (ht );
349
- HT_FLAGS ( ht ) &= ~ HASH_FLAG_PACKED ;
350
+ // Alloc before assign to avoid inconsistencies on OOM
350
351
new_data = pemalloc (HT_SIZE_EX (nSize , HT_SIZE_TO_MASK (nSize )), GC_FLAGS (ht ) & IS_ARRAY_PERSISTENT );
352
+ HT_FLAGS (ht ) &= ~HASH_FLAG_PACKED ;
351
353
ht -> nTableMask = HT_SIZE_TO_MASK (ht -> nTableSize );
352
354
HT_SET_DATA_ADDR (ht , new_data );
353
355
memcpy (ht -> arData , old_buckets , sizeof (Bucket ) * ht -> nNumUsed );
@@ -387,17 +389,18 @@ ZEND_API void ZEND_FASTCALL zend_hash_extend(HashTable *ht, uint32_t nSize, bool
387
389
if (packed ) {
388
390
ZEND_ASSERT (HT_FLAGS (ht ) & HASH_FLAG_PACKED );
389
391
if (nSize > ht -> nTableSize ) {
390
- ht -> nTableSize = zend_hash_check_size (nSize );
391
- HT_SET_DATA_ADDR (ht , perealloc2 (HT_GET_DATA_ADDR (ht ), HT_SIZE_EX (ht -> nTableSize , HT_MIN_MASK ), HT_USED_SIZE (ht ), GC_FLAGS (ht ) & IS_ARRAY_PERSISTENT ));
392
+ uint32_t newTableSize = zend_hash_check_size (nSize );
393
+ HT_SET_DATA_ADDR (ht , perealloc2 (HT_GET_DATA_ADDR (ht ), HT_SIZE_EX (newTableSize , HT_MIN_MASK ), HT_USED_SIZE (ht ), GC_FLAGS (ht ) & IS_ARRAY_PERSISTENT ));
394
+ ht -> nTableSize = newTableSize ;
392
395
}
393
396
} else {
394
397
ZEND_ASSERT (!(HT_FLAGS (ht ) & HASH_FLAG_PACKED ));
395
398
if (nSize > ht -> nTableSize ) {
396
399
void * new_data , * old_data = HT_GET_DATA_ADDR (ht );
397
400
Bucket * old_buckets = ht -> arData ;
398
401
nSize = zend_hash_check_size (nSize );
399
- ht -> nTableSize = nSize ;
400
402
new_data = pemalloc (HT_SIZE_EX (nSize , HT_SIZE_TO_MASK (nSize )), GC_FLAGS (ht ) & IS_ARRAY_PERSISTENT );
403
+ ht -> nTableSize = nSize ;
401
404
ht -> nTableMask = HT_SIZE_TO_MASK (ht -> nTableSize );
402
405
HT_SET_DATA_ADDR (ht , new_data );
403
406
memcpy (ht -> arData , old_buckets , sizeof (Bucket ) * ht -> nNumUsed );
@@ -1217,8 +1220,8 @@ static void ZEND_FASTCALL zend_hash_do_resize(HashTable *ht)
1217
1220
1218
1221
ZEND_ASSERT (HT_SIZE_TO_MASK (nSize ));
1219
1222
1220
- ht -> nTableSize = nSize ;
1221
1223
new_data = pemalloc (HT_SIZE_EX (nSize , HT_SIZE_TO_MASK (nSize )), GC_FLAGS (ht ) & IS_ARRAY_PERSISTENT );
1224
+ ht -> nTableSize = nSize ;
1222
1225
ht -> nTableMask = HT_SIZE_TO_MASK (ht -> nTableSize );
1223
1226
HT_SET_DATA_ADDR (ht , new_data );
1224
1227
memcpy (ht -> arData , old_buckets , sizeof (Bucket ) * ht -> nNumUsed );
0 commit comments