From c035298eb2cf309c486c0652ae5706e961e1fd1f Mon Sep 17 00:00:00 2001 From: Dmitry Stogov Date: Tue, 8 Feb 2022 15:45:40 +0300 Subject: [PATCH] Free cached chunks when the requested memory limit is above real usage --- Zend/zend_alloc.c | 15 ++++++++++++++- 1 file changed, 14 insertions(+), 1 deletion(-) diff --git a/Zend/zend_alloc.c b/Zend/zend_alloc.c index 5738c030a58..6e0ce4b651d 100644 --- a/Zend/zend_alloc.c +++ b/Zend/zend_alloc.c @@ -2660,10 +2660,23 @@ ZEND_API char* ZEND_FASTCALL zend_strndup(const char *s, size_t length) ZEND_API zend_result zend_set_memory_limit_ex(size_t memory_limit) { #if ZEND_MM_LIMIT + zend_mm_heap *heap = AG(mm_heap); + if (memory_limit < ZEND_MM_CHUNK_SIZE) { memory_limit = ZEND_MM_CHUNK_SIZE; } - if (UNEXPECTED(memory_limit < AG(mm_heap)->real_size)) { + if (UNEXPECTED(memory_limit < heap->real_size)) { + if (memory_limit >= heap->real_size - heap->cached_chunks_count * ZEND_MM_CHUNK_SIZE) { + /* free some cached chunks to fit into new memory limit */ + do { + zend_mm_chunk *p = heap->cached_chunks; + heap->cached_chunks = p->next; + zend_mm_chunk_free(heap, p, ZEND_MM_CHUNK_SIZE); + heap->cached_chunks_count--; + heap->real_size -= ZEND_MM_CHUNK_SIZE; + } while (memory_limit < heap->real_size); + return SUCCESS; + } return FAILURE; } AG(mm_heap)->limit = memory_limit;