@@ -2221,6 +2221,7 @@ void zend_mm_shutdown(zend_mm_heap *heap, int full, int silent)
2221
2221
/* Make sure the heap free below does not use tracked_free(). */
2222
2222
heap -> custom_heap .std ._free = free ;
2223
2223
}
2224
+ heap -> size = 0 ;
2224
2225
}
2225
2226
2226
2227
if (full ) {
@@ -2696,41 +2697,67 @@ ZEND_API void shutdown_memory_manager(int silent, int full_shutdown)
2696
2697
}
2697
2698
2698
2699
#if ZEND_MM_CUSTOM
2699
- static void * tracked_malloc (size_t size )
2700
- {
2701
- zend_mm_heap * heap = AG (mm_heap );
2702
- if (size > heap -> limit ) {
2700
+ static zend_always_inline void tracked_add (zend_mm_heap * heap , void * ptr , size_t size ) {
2701
+ zval size_zv ;
2702
+ zend_ulong h = ((uintptr_t ) ptr ) >> ZEND_MM_ALIGNMENT_LOG2 ;
2703
+ ZEND_ASSERT ((void * ) (uintptr_t ) (h << ZEND_MM_ALIGNMENT_LOG2 ) == ptr );
2704
+ ZVAL_LONG (& size_zv , size );
2705
+ zend_hash_index_add_new (heap -> tracked_allocs , h , & size_zv );
2706
+ }
2707
+
2708
+ static zend_always_inline size_t tracked_del (zend_mm_heap * heap , void * ptr ) {
2709
+ if (!ptr ) {
2710
+ return 0 ;
2711
+ }
2712
+
2713
+ zend_ulong h = ((uintptr_t ) ptr ) >> ZEND_MM_ALIGNMENT_LOG2 ;
2714
+ zval * size_zv = zend_hash_index_find (heap -> tracked_allocs , h );
2715
+ ZEND_ASSERT (size_zv && "Trying to free pointer not allocated through ZendMM" );
2716
+ zend_hash_del_bucket (heap -> tracked_allocs , (Bucket * ) size_zv );
2717
+ return Z_LVAL_P (size_zv );
2718
+ }
2719
+
2720
+ static zend_always_inline void tracked_check_limit (zend_mm_heap * heap , size_t add_size ) {
2721
+ if (add_size > heap -> limit - heap -> size && !heap -> overflow ) {
2703
2722
#if ZEND_DEBUG
2704
2723
zend_mm_safe_error (heap ,
2705
2724
"Allowed memory size of %zu bytes exhausted at %s:%d (tried to allocate %zu bytes)" ,
2706
- heap -> limit , "file" , 0 , size );
2725
+ heap -> limit , "file" , 0 , add_size );
2707
2726
#else
2708
2727
zend_mm_safe_error (heap ,
2709
2728
"Allowed memory size of %zu bytes exhausted (tried to allocate %zu bytes)" ,
2710
- heap -> limit , size );
2729
+ heap -> limit , add_size );
2711
2730
#endif
2712
2731
}
2732
+ }
2733
+
2734
+ static void * tracked_malloc (size_t size )
2735
+ {
2736
+ zend_mm_heap * heap = AG (mm_heap );
2737
+ tracked_check_limit (heap , size );
2713
2738
2714
2739
void * ptr = __zend_malloc (size );
2715
- zend_ulong h = ((uintptr_t ) ptr ) >> ZEND_MM_ALIGNMENT_LOG2 ;
2716
- ZEND_ASSERT ((void * ) (uintptr_t ) (h << ZEND_MM_ALIGNMENT_LOG2 ) == ptr );
2717
- zend_hash_index_add_empty_element (heap -> tracked_allocs , h );
2740
+ tracked_add (heap , ptr , size );
2741
+ heap -> size += size ;
2718
2742
return ptr ;
2719
2743
}
2720
2744
2721
2745
static void tracked_free (void * ptr ) {
2722
- zend_ulong h = (( uintptr_t ) ptr ) >> ZEND_MM_ALIGNMENT_LOG2 ;
2723
- zend_hash_index_del ( AG ( mm_heap ) -> tracked_allocs , h );
2746
+ zend_mm_heap * heap = AG ( mm_heap ) ;
2747
+ heap -> size -= tracked_del ( heap , ptr );
2724
2748
free (ptr );
2725
2749
}
2726
2750
2727
2751
static void * tracked_realloc (void * ptr , size_t new_size ) {
2728
- zend_ulong h = ((uintptr_t ) ptr ) >> ZEND_MM_ALIGNMENT_LOG2 ;
2729
- zend_hash_index_del (AG (mm_heap )-> tracked_allocs , h );
2752
+ zend_mm_heap * heap = AG (mm_heap );
2753
+ size_t old_size = tracked_del (heap , ptr );
2754
+ if (new_size > old_size ) {
2755
+ tracked_check_limit (heap , new_size - old_size );
2756
+ }
2757
+
2730
2758
ptr = __zend_realloc (ptr , new_size );
2731
- h = ((uintptr_t ) ptr ) >> ZEND_MM_ALIGNMENT_LOG2 ;
2732
- ZEND_ASSERT ((void * ) (uintptr_t ) (h << ZEND_MM_ALIGNMENT_LOG2 ) == ptr );
2733
- zend_hash_index_add_empty_element (AG (mm_heap )-> tracked_allocs , h );
2759
+ tracked_add (heap , ptr , new_size );
2760
+ heap -> size += new_size - old_size ;
2734
2761
return ptr ;
2735
2762
}
2736
2763
0 commit comments