Skip to content

Commit bd6feb7

Browse files
committed
Enforce memory limit in tracked allocation mode
A very basic limit (for single allocations) was already enforced. This extends it to count the total memory allocations. This is useful to avoid out of memory conditions while fuzzing.
1 parent 3ead24e commit bd6feb7

File tree

1 file changed

+43
-16
lines changed

1 file changed

+43
-16
lines changed

Zend/zend_alloc.c

Lines changed: 43 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -2221,6 +2221,7 @@ void zend_mm_shutdown(zend_mm_heap *heap, int full, int silent)
22212221
/* Make sure the heap free below does not use tracked_free(). */
22222222
heap->custom_heap.std._free = free;
22232223
}
2224+
heap->size = 0;
22242225
}
22252226

22262227
if (full) {
@@ -2696,41 +2697,67 @@ ZEND_API void shutdown_memory_manager(int silent, int full_shutdown)
26962697
}
26972698

26982699
#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) {
27032722
#if ZEND_DEBUG
27042723
zend_mm_safe_error(heap,
27052724
"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);
27072726
#else
27082727
zend_mm_safe_error(heap,
27092728
"Allowed memory size of %zu bytes exhausted (tried to allocate %zu bytes)",
2710-
heap->limit, size);
2729+
heap->limit, add_size);
27112730
#endif
27122731
}
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);
27132738

27142739
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;
27182742
return ptr;
27192743
}
27202744

27212745
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);
27242748
free(ptr);
27252749
}
27262750

27272751
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+
27302758
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;
27342761
return ptr;
27352762
}
27362763

0 commit comments

Comments
 (0)