@@ -314,8 +314,9 @@ ZEND_API void ZEND_FASTCALL zend_hash_packed_grow(HashTable *ht)
314314 if (ht -> nTableSize >= HT_MAX_SIZE ) {
315315 zend_error_noreturn (E_ERROR , "Possible integer overflow in memory allocation (%u * %zu + %zu)" , ht -> nTableSize * 2 , sizeof (Bucket ), sizeof (Bucket ));
316316 }
317- ht -> nTableSize += ht -> nTableSize ;
318- HT_SET_DATA_ADDR (ht , perealloc2 (HT_GET_DATA_ADDR (ht ), HT_PACKED_SIZE_EX (ht -> nTableSize , HT_MIN_MASK ), HT_PACKED_USED_SIZE (ht ), GC_FLAGS (ht ) & IS_ARRAY_PERSISTENT ));
317+ uint32_t newTableSize = ht -> nTableSize * 2 ;
318+ HT_SET_DATA_ADDR (ht , perealloc2 (HT_GET_DATA_ADDR (ht ), HT_PACKED_SIZE_EX (newTableSize , HT_MIN_MASK ), HT_PACKED_USED_SIZE (ht ), GC_FLAGS (ht ) & IS_ARRAY_PERSISTENT ));
319+ ht -> nTableSize = newTableSize ;
319320}
320321
321322ZEND_API void ZEND_FASTCALL zend_hash_real_init (HashTable * ht , bool packed )
@@ -353,8 +354,9 @@ ZEND_API void ZEND_FASTCALL zend_hash_packed_to_hash(HashTable *ht)
353354 ZEND_ASSERT (HT_SIZE_TO_MASK (nSize ));
354355
355356 HT_ASSERT_RC1 (ht );
356- HT_FLAGS ( ht ) &= ~ HASH_FLAG_PACKED ;
357+ // Alloc before assign to avoid inconsistencies on OOM
357358 new_data = pemalloc (HT_SIZE_EX (nSize , HT_SIZE_TO_MASK (nSize )), GC_FLAGS (ht ) & IS_ARRAY_PERSISTENT );
359+ HT_FLAGS (ht ) &= ~HASH_FLAG_PACKED ;
358360 ht -> nTableMask = HT_SIZE_TO_MASK (ht -> nTableSize );
359361 HT_SET_DATA_ADDR (ht , new_data );
360362 dst = ht -> arData ;
@@ -408,17 +410,18 @@ ZEND_API void ZEND_FASTCALL zend_hash_extend(HashTable *ht, uint32_t nSize, bool
408410 if (packed ) {
409411 ZEND_ASSERT (HT_IS_PACKED (ht ));
410412 if (nSize > ht -> nTableSize ) {
411- ht -> nTableSize = zend_hash_check_size (nSize );
412- HT_SET_DATA_ADDR (ht , perealloc2 (HT_GET_DATA_ADDR (ht ), HT_PACKED_SIZE_EX (ht -> nTableSize , HT_MIN_MASK ), HT_PACKED_USED_SIZE (ht ), GC_FLAGS (ht ) & IS_ARRAY_PERSISTENT ));
413+ uint32_t newTableSize = zend_hash_check_size (nSize );
414+ HT_SET_DATA_ADDR (ht , perealloc2 (HT_GET_DATA_ADDR (ht ), HT_PACKED_SIZE_EX (newTableSize , HT_MIN_MASK ), HT_PACKED_USED_SIZE (ht ), GC_FLAGS (ht ) & IS_ARRAY_PERSISTENT ));
415+ ht -> nTableSize = newTableSize ;
413416 }
414417 } else {
415418 ZEND_ASSERT (!HT_IS_PACKED (ht ));
416419 if (nSize > ht -> nTableSize ) {
417420 void * new_data , * old_data = HT_GET_DATA_ADDR (ht );
418421 Bucket * old_buckets = ht -> arData ;
419422 nSize = zend_hash_check_size (nSize );
420- ht -> nTableSize = nSize ;
421423 new_data = pemalloc (HT_SIZE_EX (nSize , HT_SIZE_TO_MASK (nSize )), GC_FLAGS (ht ) & IS_ARRAY_PERSISTENT );
424+ ht -> nTableSize = nSize ;
422425 ht -> nTableMask = HT_SIZE_TO_MASK (ht -> nTableSize );
423426 HT_SET_DATA_ADDR (ht , new_data );
424427 memcpy (ht -> arData , old_buckets , sizeof (Bucket ) * ht -> nNumUsed );
@@ -1247,8 +1250,8 @@ static void ZEND_FASTCALL zend_hash_do_resize(HashTable *ht)
12471250
12481251 ZEND_ASSERT (HT_SIZE_TO_MASK (nSize ));
12491252
1250- ht -> nTableSize = nSize ;
12511253 new_data = pemalloc (HT_SIZE_EX (nSize , HT_SIZE_TO_MASK (nSize )), GC_FLAGS (ht ) & IS_ARRAY_PERSISTENT );
1254+ ht -> nTableSize = nSize ;
12521255 ht -> nTableMask = HT_SIZE_TO_MASK (ht -> nTableSize );
12531256 HT_SET_DATA_ADDR (ht , new_data );
12541257 memcpy (ht -> arData , old_buckets , sizeof (Bucket ) * ht -> nNumUsed );
0 commit comments