@@ -317,7 +317,9 @@ struct _zend_mm_heap {
317317 } debug ;
318318 };
319319#endif
320+ #if ZEND_DEBUG
320321 pid_t pid ;
322+ #endif
321323 zend_random_bytes_insecure_state rand_state ;
322324};
323325
@@ -1310,15 +1312,20 @@ static zend_always_inline zend_mm_free_slot* zend_mm_encode_free_slot(const zend
13101312#endif
13111313}
13121314
1313- static zend_always_inline zend_mm_free_slot * zend_mm_decode_free_slot ( zend_mm_heap * heap , zend_mm_free_slot * slot )
1315+ static zend_always_inline zend_mm_free_slot * zend_mm_decode_free_slot_key ( uintptr_t shadow_key , zend_mm_free_slot * slot )
13141316{
13151317#ifdef WORDS_BIGENDIAN
1316- return (zend_mm_free_slot * )((uintptr_t )slot ^ heap -> shadow_key );
1318+ return (zend_mm_free_slot * )((uintptr_t )slot ^ shadow_key );
13171319#else
1318- return (zend_mm_free_slot * )(BSWAPPTR ((uintptr_t )slot ^ heap -> shadow_key ));
1320+ return (zend_mm_free_slot * )(BSWAPPTR ((uintptr_t )slot ^ shadow_key ));
13191321#endif
13201322}
13211323
1324+ static zend_always_inline zend_mm_free_slot * zend_mm_decode_free_slot (zend_mm_heap * heap , zend_mm_free_slot * slot )
1325+ {
1326+ return zend_mm_decode_free_slot_key (heap -> shadow_key , slot );
1327+ }
1328+
13221329static zend_always_inline void zend_mm_set_next_free_slot (zend_mm_heap * heap , uint32_t bin_num , zend_mm_free_slot * slot , zend_mm_free_slot * next )
13231330{
13241331 ZEND_ASSERT (bin_data_size [bin_num ] >= ZEND_MM_MIN_USEABLE_BIN_SIZE );
@@ -2027,6 +2034,34 @@ static void zend_mm_init_key(zend_mm_heap *heap)
20272034 zend_mm_refresh_key (heap );
20282035}
20292036
2037+ ZEND_API void zend_mm_refresh_key_child (zend_mm_heap * heap )
2038+ {
2039+ uintptr_t old_key = heap -> shadow_key ;
2040+
2041+ zend_mm_init_key (heap );
2042+
2043+ /* Update shadow pointers with new key */
2044+ for (int i = 0 ; i < ZEND_MM_BINS ; i ++ ) {
2045+ zend_mm_free_slot * slot = heap -> free_slot [i ];
2046+ if (!slot ) {
2047+ continue ;
2048+ }
2049+ zend_mm_free_slot * next ;
2050+ while ((next = slot -> next_free_slot )) {
2051+ zend_mm_free_slot * shadow = ZEND_MM_FREE_SLOT_PTR_SHADOW (slot , i );
2052+ if (UNEXPECTED (next != zend_mm_decode_free_slot_key (old_key , shadow ))) {
2053+ zend_mm_panic ("zend_mm_heap corrupted" );
2054+ }
2055+ zend_mm_set_next_free_slot (heap , i , slot , next );
2056+ slot = next ;
2057+ }
2058+ }
2059+
2060+ #if ZEND_DEBUG
2061+ heap -> pid = getpid ();
2062+ #endif
2063+ }
2064+
20302065static zend_mm_heap * zend_mm_init (void )
20312066{
20322067 zend_mm_chunk * chunk = (zend_mm_chunk * )zend_mm_chunk_alloc_int (ZEND_MM_CHUNK_SIZE , ZEND_MM_CHUNK_SIZE );
@@ -2075,7 +2110,9 @@ static zend_mm_heap *zend_mm_init(void)
20752110 heap -> storage = NULL ;
20762111#endif
20772112 heap -> huge_list = NULL ;
2113+ #if ZEND_DEBUG
20782114 heap -> pid = getpid ();
2115+ #endif
20792116 return heap ;
20802117}
20812118
@@ -2535,13 +2572,12 @@ ZEND_API void zend_mm_shutdown(zend_mm_heap *heap, bool full, bool silent)
25352572 p -> free_map [0 ] = (1L << ZEND_MM_FIRST_PAGE ) - 1 ;
25362573 p -> map [0 ] = ZEND_MM_LRUN (ZEND_MM_FIRST_PAGE );
25372574
2538- pid_t pid = getpid ();
2539- if (heap -> pid != pid ) {
2540- zend_mm_init_key (heap );
2541- heap -> pid = pid ;
2542- } else {
2543- zend_mm_refresh_key (heap );
2544- }
2575+ #if ZEND_DEBUG
2576+ ZEND_ASSERT (getpid () == heap -> pid
2577+ && "heap was re-used without calling zend_mm_refresh_key_child() after a fork" );
2578+ #endif
2579+
2580+ zend_mm_refresh_key (heap );
25452581 }
25462582}
25472583
@@ -2949,6 +2985,11 @@ ZEND_API void shutdown_memory_manager(bool silent, bool full_shutdown)
29492985 zend_mm_shutdown (AG (mm_heap ), full_shutdown , silent );
29502986}
29512987
2988+ ZEND_API void refresh_memory_manager (void )
2989+ {
2990+ zend_mm_refresh_key_child (AG (mm_heap ));
2991+ }
2992+
29522993static ZEND_COLD ZEND_NORETURN void zend_out_of_memory (void )
29532994{
29542995 fprintf (stderr , "Out of memory\n" );
@@ -3506,7 +3547,9 @@ ZEND_API zend_mm_heap *zend_mm_startup_ex(const zend_mm_handlers *handlers, void
35063547 memcpy (storage -> data , data , data_size );
35073548 }
35083549 heap -> storage = storage ;
3550+ #if ZEND_DEBUG
35093551 heap -> pid = getpid ();
3552+ #endif
35103553 return heap ;
35113554#else
35123555 return NULL ;
0 commit comments