@@ -304,8 +304,9 @@ ZEND_API void ZEND_FASTCALL zend_hash_packed_grow(HashTable *ht)
304304 if (ht -> nTableSize >= HT_MAX_SIZE ) {
305305 zend_error_noreturn (E_ERROR , "Possible integer overflow in memory allocation (%u * %zu + %zu)" , ht -> nTableSize * 2 , sizeof (Bucket ), sizeof (Bucket ));
306306 }
307- ht -> nTableSize += ht -> nTableSize ;
308- 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 ));
307+ uint32_t newTableSize = ht -> nTableSize * 2 ;
308+ 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 ));
309+ ht -> nTableSize = newTableSize ;
309310}
310311
311312ZEND_API void ZEND_FASTCALL zend_hash_real_init (HashTable * ht , bool packed )
@@ -343,8 +344,9 @@ ZEND_API void ZEND_FASTCALL zend_hash_packed_to_hash(HashTable *ht)
343344 ZEND_ASSERT (HT_SIZE_TO_MASK (nSize ));
344345
345346 HT_ASSERT_RC1 (ht );
346- HT_FLAGS ( ht ) &= ~ HASH_FLAG_PACKED ;
347+ // Alloc before assign to avoid inconsistencies on OOM
347348 new_data = pemalloc (HT_SIZE_EX (nSize , HT_SIZE_TO_MASK (nSize )), GC_FLAGS (ht ) & IS_ARRAY_PERSISTENT );
349+ HT_FLAGS (ht ) &= ~HASH_FLAG_PACKED ;
348350 ht -> nTableMask = HT_SIZE_TO_MASK (ht -> nTableSize );
349351 HT_SET_DATA_ADDR (ht , new_data );
350352 dst = ht -> arData ;
@@ -398,17 +400,18 @@ ZEND_API void ZEND_FASTCALL zend_hash_extend(HashTable *ht, uint32_t nSize, bool
398400 if (packed ) {
399401 ZEND_ASSERT (HT_IS_PACKED (ht ));
400402 if (nSize > ht -> nTableSize ) {
401- ht -> nTableSize = zend_hash_check_size (nSize );
402- 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 ));
403+ uint32_t newTableSize = zend_hash_check_size (nSize );
404+ 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 ));
405+ ht -> nTableSize = newTableSize ;
403406 }
404407 } else {
405408 ZEND_ASSERT (!HT_IS_PACKED (ht ));
406409 if (nSize > ht -> nTableSize ) {
407410 void * new_data , * old_data = HT_GET_DATA_ADDR (ht );
408411 Bucket * old_buckets = ht -> arData ;
409412 nSize = zend_hash_check_size (nSize );
410- ht -> nTableSize = nSize ;
411413 new_data = pemalloc (HT_SIZE_EX (nSize , HT_SIZE_TO_MASK (nSize )), GC_FLAGS (ht ) & IS_ARRAY_PERSISTENT );
414+ ht -> nTableSize = nSize ;
412415 ht -> nTableMask = HT_SIZE_TO_MASK (ht -> nTableSize );
413416 HT_SET_DATA_ADDR (ht , new_data );
414417 memcpy (ht -> arData , old_buckets , sizeof (Bucket ) * ht -> nNumUsed );
@@ -1237,8 +1240,8 @@ static void ZEND_FASTCALL zend_hash_do_resize(HashTable *ht)
12371240
12381241 ZEND_ASSERT (HT_SIZE_TO_MASK (nSize ));
12391242
1240- ht -> nTableSize = nSize ;
12411243 new_data = pemalloc (HT_SIZE_EX (nSize , HT_SIZE_TO_MASK (nSize )), GC_FLAGS (ht ) & IS_ARRAY_PERSISTENT );
1244+ ht -> nTableSize = nSize ;
12421245 ht -> nTableMask = HT_SIZE_TO_MASK (ht -> nTableSize );
12431246 HT_SET_DATA_ADDR (ht , new_data );
12441247 memcpy (ht -> arData , old_buckets , sizeof (Bucket ) * ht -> nNumUsed );
0 commit comments