From 49959eb4d3eaed0d2f42a4f2e986fa67413882dd Mon Sep 17 00:00:00 2001 From: ndossche <7771979+ndossche@users.noreply.github.com> Date: Sun, 24 May 2026 18:42:37 +0200 Subject: [PATCH] Fix memory leak (and heap corruption) in getDensity() function Memory returned by `DrawGetDensity()` must be freed by `MagickRelinquishMemory()`. This also means that the PHP 5-era code will cause heap corruption as it doesn't duplicate the string and will free memory via ZendMM even though the memory doesn't come from ZendMM. Fix the macros and fix the missing free. ASAN report: ``` Direct leak of 4099 byte(s) in 1 object(s) allocated from: #0 0x77ebf1bc59c7 in malloc ../../../../src/libsanitizer/asan/asan_malloc_linux.cpp:69 #1 0x77ebeb7ad28b in AcquireString MagickCore/string.c:109 #2 0x77ebeca40c9a in zim_ImagickDraw_getDensity /work/php-imagemagick/imagickdraw_class.c:3067 #3 0x5bd4b54c9395 in zend_test_execute_internal /work/php-src/ext/zend_test/observer.c:306 #4 0x5bd4b57f170a in ZEND_DO_FCALL_SPEC_RETVAL_USED_HANDLER /work/php-src/Zend/zend_vm_execute.h:2154 #5 0x5bd4b5951e55 in execute_ex /work/php-src/Zend/zend_vm_execute.h:116519 #6 0x5bd4b5966d70 in zend_execute /work/php-src/Zend/zend_vm_execute.h:121962 #7 0x5bd4b5acb56b in zend_execute_script /work/php-src/Zend/zend.c:1980 #8 0x5bd4b54fdd7b in php_execute_script_ex /work/php-src/main/main.c:2645 #9 0x5bd4b54fe18b in php_execute_script /work/php-src/main/main.c:2685 #10 0x5bd4b5ad10d6 in do_cli /work/php-src/sapi/cli/php_cli.c:951 #11 0x5bd4b5ad36a3 in main /work/php-src/sapi/cli/php_cli.c:1362 #12 0x77ebf0ea31c9 in __libc_start_call_main ../sysdeps/nptl/libc_start_call_main.h:58 #13 0x77ebf0ea328a in __libc_start_main_impl ../csu/libc-start.c:360 #14 0x5bd4b4609df4 in _start (/work/php-src/build-dbg-asan/sapi/cli/php+0x609df4) (BuildId: 97494815ba6ad97379608f28619e331873dc4434) ``` --- imagickdraw_class.c | 3 ++- php_imagick_defs.h | 4 ++-- 2 files changed, 4 insertions(+), 3 deletions(-) diff --git a/imagickdraw_class.c b/imagickdraw_class.c index 0d1f0f7d..fe26494d 100644 --- a/imagickdraw_class.c +++ b/imagickdraw_class.c @@ -3070,7 +3070,8 @@ PHP_METHOD(ImagickDraw, getDensity) RETURN_NULL(); } else { - IM_RETURN_STRING(density); + IM_RETVAL_STRING(density); + MagickRelinquishMemory(density); } } /* }}} */ diff --git a/php_imagick_defs.h b/php_imagick_defs.h index 2c5f990a..57abb4d2 100644 --- a/php_imagick_defs.h +++ b/php_imagick_defs.h @@ -322,11 +322,11 @@ static inline php_imagickkernel_object *php_imagickkernel_fetch_object(zend_obje // String access #if PHP_VERSION_ID >= 70000 #define IM_ZVAL_STRING(zv, charstar) ZVAL_STRING(zv, charstar); - #define IM_RETURN_STRING(s) RETURN_STRING(s) + #define IM_RETVAL_STRING(s) RETVAL_STRING(s) #else #define IM_ZVAL_STRING(zv, charstar) ZVAL_STRING(zv, charstar, 1); //RETURN_STRING(s, duplicate) - #define IM_RETURN_STRING(s) RETURN_STRING(s, 0) + #define IM_RETVAL_STRING(s) RETVAL_STRING(s, 1) #endif #if PHP_VERSION_ID >= 70000