@@ -309,8 +309,9 @@ ZEND_API void ZEND_FASTCALL zend_hash_packed_grow(HashTable *ht)
309309 if (ht -> nTableSize >= HT_MAX_SIZE ) {
310310 zend_error_noreturn (E_ERROR , "Possible integer overflow in memory allocation (%u * %zu + %zu)" , ht -> nTableSize * 2 , sizeof (Bucket ), sizeof (Bucket ));
311311 }
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 ;
314315}
315316
316317ZEND_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)
346347 ZEND_ASSERT (HT_SIZE_TO_MASK (nSize ));
347348
348349 HT_ASSERT_RC1 (ht );
349- HT_FLAGS ( ht ) &= ~ HASH_FLAG_PACKED ;
350+ // Alloc before assign to avoid inconsistencies on OOM
350351 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 ;
351353 ht -> nTableMask = HT_SIZE_TO_MASK (ht -> nTableSize );
352354 HT_SET_DATA_ADDR (ht , new_data );
353355 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
387389 if (packed ) {
388390 ZEND_ASSERT (HT_FLAGS (ht ) & HASH_FLAG_PACKED );
389391 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 ;
392395 }
393396 } else {
394397 ZEND_ASSERT (!(HT_FLAGS (ht ) & HASH_FLAG_PACKED ));
395398 if (nSize > ht -> nTableSize ) {
396399 void * new_data , * old_data = HT_GET_DATA_ADDR (ht );
397400 Bucket * old_buckets = ht -> arData ;
398401 nSize = zend_hash_check_size (nSize );
399- ht -> nTableSize = nSize ;
400402 new_data = pemalloc (HT_SIZE_EX (nSize , HT_SIZE_TO_MASK (nSize )), GC_FLAGS (ht ) & IS_ARRAY_PERSISTENT );
403+ ht -> nTableSize = nSize ;
401404 ht -> nTableMask = HT_SIZE_TO_MASK (ht -> nTableSize );
402405 HT_SET_DATA_ADDR (ht , new_data );
403406 memcpy (ht -> arData , old_buckets , sizeof (Bucket ) * ht -> nNumUsed );
@@ -1217,8 +1220,8 @@ static void ZEND_FASTCALL zend_hash_do_resize(HashTable *ht)
12171220
12181221 ZEND_ASSERT (HT_SIZE_TO_MASK (nSize ));
12191222
1220- ht -> nTableSize = nSize ;
12211223 new_data = pemalloc (HT_SIZE_EX (nSize , HT_SIZE_TO_MASK (nSize )), GC_FLAGS (ht ) & IS_ARRAY_PERSISTENT );
1224+ ht -> nTableSize = nSize ;
12221225 ht -> nTableMask = HT_SIZE_TO_MASK (ht -> nTableSize );
12231226 HT_SET_DATA_ADDR (ht , new_data );
12241227 memcpy (ht -> arData , old_buckets , sizeof (Bucket ) * ht -> nNumUsed );
0 commit comments