From 504a130f5a73d1f16260a77cb948011a97f50425 Mon Sep 17 00:00:00 2001 From: Florian Engelhardt Date: Tue, 20 Feb 2024 13:51:55 +0100 Subject: [PATCH 1/4] add gc and shutdown callbacks --- Zend/zend_alloc.c | 57 +++++- Zend/zend_alloc.h | 18 +- ext/zend_test/config.m4 | 2 +- ext/zend_test/config.w32 | 2 +- ext/zend_test/php_test.h | 13 ++ ext/zend_test/test.c | 9 +- .../zend_mm_custom_handlers_alloc_01.phpt | 12 ++ .../zend_mm_custom_handlers_free_01.phpt | 13 ++ .../tests/zend_mm_custom_handlers_gc_01.phpt | 12 ++ ext/zend_test/zend_mm_custom_handlers.c | 172 ++++++++++++++++++ ext/zend_test/zend_mm_custom_handlers.h | 24 +++ sapi/phpdbg/phpdbg.c | 8 +- 12 files changed, 322 insertions(+), 20 deletions(-) create mode 100644 ext/zend_test/tests/zend_mm_custom_handlers_alloc_01.phpt create mode 100644 ext/zend_test/tests/zend_mm_custom_handlers_free_01.phpt create mode 100644 ext/zend_test/tests/zend_mm_custom_handlers_gc_01.phpt create mode 100644 ext/zend_test/zend_mm_custom_handlers.c create mode 100644 ext/zend_test/zend_mm_custom_handlers.h diff --git a/Zend/zend_alloc.c b/Zend/zend_alloc.c index ed683d65fa221..c69ff5759beeb 100644 --- a/Zend/zend_alloc.c +++ b/Zend/zend_alloc.c @@ -334,6 +334,8 @@ struct _zend_mm_heap { void *(*_malloc)(size_t ZEND_FILE_LINE_DC ZEND_FILE_LINE_ORIG_DC); void (*_free)(void* ZEND_FILE_LINE_DC ZEND_FILE_LINE_ORIG_DC); void *(*_realloc)(void*, size_t ZEND_FILE_LINE_DC ZEND_FILE_LINE_ORIG_DC); + size_t (*_gc)(void); + void (*_shutdown)(bool full, bool silent); } custom_heap; HashTable *tracked_allocs; #endif @@ -2119,6 +2121,10 @@ ZEND_API size_t zend_mm_gc(zend_mm_heap *heap) #if ZEND_MM_CUSTOM if (heap->use_custom_heap) { + size_t (*gc)(void) = heap->custom_heap._gc; + if (gc) { + return gc(); + } return 0; } #endif @@ -2421,10 +2427,10 @@ static void zend_mm_check_leaks(zend_mm_heap *heap) #if ZEND_MM_CUSTOM static void *tracked_malloc(size_t size ZEND_FILE_LINE_DC ZEND_FILE_LINE_ORIG_DC); -static void tracked_free_all(void); +static void tracked_free_all(zend_mm_heap *heap); #endif -void zend_mm_shutdown(zend_mm_heap *heap, bool full, bool silent) +ZEND_API void zend_mm_shutdown(zend_mm_heap *heap, bool full, bool silent) { zend_mm_chunk *p; zend_mm_huge_list *list; @@ -2433,7 +2439,7 @@ void zend_mm_shutdown(zend_mm_heap *heap, bool full, bool silent) if (heap->use_custom_heap) { if (heap->custom_heap._malloc == tracked_malloc) { if (silent) { - tracked_free_all(); + tracked_free_all(heap); } zend_hash_clean(heap->tracked_allocs); if (full) { @@ -2445,9 +2451,16 @@ void zend_mm_shutdown(zend_mm_heap *heap, bool full, bool silent) heap->size = 0; } + void (*shutdown)(bool, bool) = heap->custom_heap._shutdown; + if (full) { heap->custom_heap._free(heap ZEND_FILE_LINE_CC ZEND_FILE_LINE_EMPTY_CC); } + + if (shutdown) { + shutdown(full, silent); + } + return; } #endif @@ -3039,8 +3052,8 @@ static void *tracked_realloc(void *ptr, size_t new_size ZEND_FILE_LINE_DC ZEND_F return ptr; } -static void tracked_free_all(void) { - HashTable *tracked_allocs = AG(mm_heap)->tracked_allocs; +static void tracked_free_all(zend_mm_heap *heap) { + HashTable *tracked_allocs = heap->tracked_allocs; zend_ulong h; ZEND_HASH_FOREACH_NUM_KEY(tracked_allocs, h) { void *ptr = (void *) (uintptr_t) (h << ZEND_MM_ALIGNMENT_LOG2); @@ -3124,6 +3137,16 @@ ZEND_API zend_mm_heap *zend_mm_get_heap(void) return AG(mm_heap); } +ZEND_API zend_mm_heap *zend_mm_heap_create(void) +{ + return zend_mm_init(); +} + +ZEND_API void zend_mm_heap_free(zend_mm_heap *heap) +{ + zend_mm_chunk_free(heap, heap->main_chunk, ZEND_MM_CHUNK_SIZE); +} + ZEND_API bool zend_mm_is_custom_heap(zend_mm_heap *new_heap) { #if ZEND_MM_CUSTOM @@ -3136,7 +3159,9 @@ ZEND_API bool zend_mm_is_custom_heap(zend_mm_heap *new_heap) ZEND_API void zend_mm_set_custom_handlers(zend_mm_heap *heap, void* (*_malloc)(size_t ZEND_FILE_LINE_DC ZEND_FILE_LINE_ORIG_DC), void (*_free)(void* ZEND_FILE_LINE_DC ZEND_FILE_LINE_ORIG_DC), - void* (*_realloc)(void*, size_t ZEND_FILE_LINE_DC ZEND_FILE_LINE_ORIG_DC)) + void* (*_realloc)(void*, size_t ZEND_FILE_LINE_DC ZEND_FILE_LINE_ORIG_DC), + size_t (*_gc)(void), + void (*_shutdown)(bool, bool)) { #if ZEND_MM_CUSTOM zend_mm_heap *_heap = (zend_mm_heap*)heap; @@ -3148,6 +3173,8 @@ ZEND_API void zend_mm_set_custom_handlers(zend_mm_heap *heap, _heap->custom_heap._malloc = _malloc; _heap->custom_heap._free = _free; _heap->custom_heap._realloc = _realloc; + _heap->custom_heap._gc = _gc; + _heap->custom_heap._shutdown = _shutdown; } #endif } @@ -3155,7 +3182,9 @@ ZEND_API void zend_mm_set_custom_handlers(zend_mm_heap *heap, ZEND_API void zend_mm_get_custom_handlers(zend_mm_heap *heap, void* (**_malloc)(size_t ZEND_FILE_LINE_DC ZEND_FILE_LINE_ORIG_DC), void (**_free)(void* ZEND_FILE_LINE_DC ZEND_FILE_LINE_ORIG_DC), - void* (**_realloc)(void*, size_t ZEND_FILE_LINE_DC ZEND_FILE_LINE_ORIG_DC)) + void* (**_realloc)(void*, size_t ZEND_FILE_LINE_DC ZEND_FILE_LINE_ORIG_DC), + size_t (**_gc)(void), + void (**_shutdown)(bool, bool)) { #if ZEND_MM_CUSTOM zend_mm_heap *_heap = (zend_mm_heap*)heap; @@ -3164,15 +3193,29 @@ ZEND_API void zend_mm_get_custom_handlers(zend_mm_heap *heap, *_malloc = _heap->custom_heap._malloc; *_free = _heap->custom_heap._free; *_realloc = _heap->custom_heap._realloc; + if (_gc != NULL) { + *_gc = _heap->custom_heap._gc; + } + if (_shutdown != NULL) { + *_shutdown = _heap->custom_heap._shutdown; + } } else { *_malloc = NULL; *_free = NULL; *_realloc = NULL; + if (_gc != NULL) { + *_gc = NULL; + } + if (_shutdown != NULL) { + *_shutdown = NULL; + } } #else *_malloc = NULL; *_free = NULL; *_realloc = NULL; + *_gc = NULL; + *_shutdown = NULL; #endif } diff --git a/Zend/zend_alloc.h b/Zend/zend_alloc.h index 2965de2b931cf..ea91228482e46 100644 --- a/Zend/zend_alloc.h +++ b/Zend/zend_alloc.h @@ -263,6 +263,8 @@ ZEND_API size_t ZEND_FASTCALL _zend_mm_block_size(zend_mm_heap *heap, void *p ZE #define zend_mm_realloc2_rel(heap, p, size, copy_size) _zend_mm_realloc2((heap), (p), (size), (copy_size) ZEND_FILE_LINE_RELAY_CC ZEND_FILE_LINE_CC) #define zend_mm_block_size_rel(heap, p) _zend_mm_block_size((heap), (p) ZEND_FILE_LINE_CC ZEND_FILE_LINE_EMPTY_CC) +ZEND_API zend_mm_heap *zend_mm_heap_create(void); +ZEND_API void zend_mm_heap_free(zend_mm_heap* heap); ZEND_API zend_mm_heap *zend_mm_set_heap(zend_mm_heap *new_heap); ZEND_API zend_mm_heap *zend_mm_get_heap(void); @@ -274,13 +276,17 @@ ZEND_API size_t zend_mm_gc(zend_mm_heap *heap); ZEND_API bool zend_mm_is_custom_heap(zend_mm_heap *new_heap); ZEND_API void zend_mm_set_custom_handlers(zend_mm_heap *heap, - void* (*_malloc)(size_t ZEND_FILE_LINE_DC ZEND_FILE_LINE_ORIG_DC), - void (*_free)(void* ZEND_FILE_LINE_DC ZEND_FILE_LINE_ORIG_DC), - void* (*_realloc)(void*, size_t ZEND_FILE_LINE_DC ZEND_FILE_LINE_ORIG_DC)); + void* (*_malloc)(size_t ZEND_FILE_LINE_DC ZEND_FILE_LINE_ORIG_DC), + void (*_free)(void* ZEND_FILE_LINE_DC ZEND_FILE_LINE_ORIG_DC), + void* (*_realloc)(void*, size_t ZEND_FILE_LINE_DC ZEND_FILE_LINE_ORIG_DC), + size_t (*_gc)(void), + void (*_shutdown)(bool, bool)); ZEND_API void zend_mm_get_custom_handlers(zend_mm_heap *heap, - void* (**_malloc)(size_t ZEND_FILE_LINE_DC ZEND_FILE_LINE_ORIG_DC), - void (**_free)(void* ZEND_FILE_LINE_DC ZEND_FILE_LINE_ORIG_DC), - void* (**_realloc)(void*, size_t ZEND_FILE_LINE_DC ZEND_FILE_LINE_ORIG_DC)); + void* (**_malloc)(size_t ZEND_FILE_LINE_DC ZEND_FILE_LINE_ORIG_DC), + void (**_free)(void* ZEND_FILE_LINE_DC ZEND_FILE_LINE_ORIG_DC), + void* (**_realloc)(void*, size_t ZEND_FILE_LINE_DC ZEND_FILE_LINE_ORIG_DC), + size_t (**_gc)(void), + void (**_shutdown)(bool, bool)); typedef struct _zend_mm_storage zend_mm_storage; diff --git a/ext/zend_test/config.m4 b/ext/zend_test/config.m4 index 4b15db47750cb..1aff6f0e58319 100644 --- a/ext/zend_test/config.m4 +++ b/ext/zend_test/config.m4 @@ -4,5 +4,5 @@ PHP_ARG_ENABLE([zend-test], [Enable zend_test extension])]) if test "$PHP_ZEND_TEST" != "no"; then - PHP_NEW_EXTENSION(zend_test, test.c observer.c fiber.c iterators.c object_handlers.c, $ext_shared,, -DZEND_ENABLE_STATIC_TSRMLS_CACHE=1) + PHP_NEW_EXTENSION(zend_test, test.c observer.c fiber.c iterators.c object_handlers.c zend_mm_custom_handlers.c, $ext_shared,, -DZEND_ENABLE_STATIC_TSRMLS_CACHE=1) fi diff --git a/ext/zend_test/config.w32 b/ext/zend_test/config.w32 index e066fdeb243ea..65fe6d359ba72 100644 --- a/ext/zend_test/config.w32 +++ b/ext/zend_test/config.w32 @@ -3,6 +3,6 @@ ARG_ENABLE("zend-test", "enable zend_test extension", "no"); if (PHP_ZEND_TEST != "no") { - EXTENSION("zend_test", "test.c observer.c fiber.c iterators.c object_handlers.c", PHP_ZEND_TEST_SHARED, "/DZEND_ENABLE_STATIC_TSRMLS_CACHE=1"); + EXTENSION("zend_test", "test.c observer.c fiber.c iterators.c object_handlers.c zend_mm_custom_handlers.c", PHP_ZEND_TEST_SHARED, "/DZEND_ENABLE_STATIC_TSRMLS_CACHE=1"); ADD_FLAG("CFLAGS_ZEND_TEST", "/D PHP_ZEND_TEST_EXPORTS "); } diff --git a/ext/zend_test/php_test.h b/ext/zend_test/php_test.h index 89570d1155cea..09391d8137aa6 100644 --- a/ext/zend_test/php_test.h +++ b/ext/zend_test/php_test.h @@ -62,6 +62,19 @@ ZEND_BEGIN_MODULE_GLOBALS(zend_test) zend_long quantity_value; zend_string *str_test; zend_string *not_empty_str_test; + int zend_mm_custom_handlers_enabled; + + // the previous heap that was found in ZendMM + zend_mm_heap* original_heap; + // the custom handlers that might have been found in the previous heap + void* (*custom_malloc)(size_t ZEND_FILE_LINE_DC ZEND_FILE_LINE_ORIG_DC); + void (*custom_free)(void* ZEND_FILE_LINE_DC ZEND_FILE_LINE_ORIG_DC); + void* (*custom_realloc)(void *, size_t ZEND_FILE_LINE_DC ZEND_FILE_LINE_ORIG_DC); + size_t (*custom_gc)(void); + void (*custom_shutdown)(bool, bool); + // this is our heap that we install our custom handlers on and inject into + // ZendMM + zend_mm_heap* observed_heap; ZEND_END_MODULE_GLOBALS(zend_test) extern ZEND_DECLARE_MODULE_GLOBALS(zend_test) diff --git a/ext/zend_test/test.c b/ext/zend_test/test.c index 78adc05ccca5e..00ecd66c7df4e 100644 --- a/ext/zend_test/test.c +++ b/ext/zend_test/test.c @@ -14,6 +14,7 @@ +----------------------------------------------------------------------+ */ +#include "zend_modules.h" #ifdef HAVE_CONFIG_H # include "config.h" #endif @@ -35,6 +36,7 @@ #include "test_arginfo.h" #include "zend_call_stack.h" #include "zend_exceptions.h" +#include "zend_mm_custom_handlers.h" // `php.h` sets `NDEBUG` when not `PHP_DEBUG` which will make `assert()` from // assert.h a no-op. In order to have `assert()` working on NDEBUG builds, we @@ -707,7 +709,9 @@ static PHP_INI_MH(OnUpdateZendTestObserveOplineInZendMM) ZT_G(zend_test_heap), zend_test_custom_malloc, zend_test_custom_free, - zend_test_custom_realloc + zend_test_custom_realloc, + NULL, + NULL ); ZT_G(zend_orig_heap) = zend_mm_get_heap(); zend_mm_set_heap(ZT_G(zend_test_heap)); @@ -1260,6 +1264,7 @@ PHP_MINIT_FUNCTION(zend_test) } zend_test_observer_init(INIT_FUNC_ARGS_PASSTHRU); + zend_test_mm_custom_handlers_minit(INIT_FUNC_ARGS_PASSTHRU); zend_test_fiber_init(); zend_test_iterators_init(); zend_test_object_handlers_init(); @@ -1288,6 +1293,7 @@ PHP_RINIT_FUNCTION(zend_test) { zend_hash_init(&ZT_G(global_weakmap), 8, NULL, ZVAL_PTR_DTOR, 0); ZT_G(observer_nesting_depth) = 0; + zend_test_mm_custom_handlers_rinit(); return SUCCESS; } @@ -1305,6 +1311,7 @@ PHP_RSHUTDOWN_FUNCTION(zend_test) zend_mm_set_heap(ZT_G(zend_orig_heap)); } + zend_test_mm_custom_handlers_rshutdown(); return SUCCESS; } diff --git a/ext/zend_test/tests/zend_mm_custom_handlers_alloc_01.phpt b/ext/zend_test/tests/zend_mm_custom_handlers_alloc_01.phpt new file mode 100644 index 0000000000000..cb6490d4c5d31 --- /dev/null +++ b/ext/zend_test/tests/zend_mm_custom_handlers_alloc_01.phpt @@ -0,0 +1,12 @@ +--TEST-- +ZendMM Custom Handlers: garbage collection +--EXTENSIONS-- +zend_test +--FILE-- + +--EXPECTREGEX-- +.*Allocated \d+ bytes at.* diff --git a/ext/zend_test/tests/zend_mm_custom_handlers_free_01.phpt b/ext/zend_test/tests/zend_mm_custom_handlers_free_01.phpt new file mode 100644 index 0000000000000..ae9dacb999509 --- /dev/null +++ b/ext/zend_test/tests/zend_mm_custom_handlers_free_01.phpt @@ -0,0 +1,13 @@ +--TEST-- +ZendMM Custom Handlers: garbage collection +--EXTENSIONS-- +zend_test +--FILE-- + +--EXPECTREGEX-- +.*Freed memory at.* diff --git a/ext/zend_test/tests/zend_mm_custom_handlers_gc_01.phpt b/ext/zend_test/tests/zend_mm_custom_handlers_gc_01.phpt new file mode 100644 index 0000000000000..c6e498ba55f80 --- /dev/null +++ b/ext/zend_test/tests/zend_mm_custom_handlers_gc_01.phpt @@ -0,0 +1,12 @@ +--TEST-- +ZendMM Custom Handlers: garbage collection +--EXTENSIONS-- +zend_test +--FILE-- + +--EXPECTREGEX-- +.*ZendMM GC freed \d+ bytes.* diff --git a/ext/zend_test/zend_mm_custom_handlers.c b/ext/zend_test/zend_mm_custom_handlers.c new file mode 100644 index 0000000000000..db178ac3ae705 --- /dev/null +++ b/ext/zend_test/zend_mm_custom_handlers.c @@ -0,0 +1,172 @@ +/* + +----------------------------------------------------------------------+ + | Copyright (c) The PHP Group | + +----------------------------------------------------------------------+ + | This source file is subject to version 3.01 of the PHP license, | + | that is bundled with this package in the file LICENSE, and is | + | available through the world-wide-web at the following url: | + | https://www.php.net/license/3_01.txt | + | If you did not receive a copy of the PHP license and are unable to | + | obtain it through the world-wide-web, please send a note to | + | license@php.net so we can mail you a copy immediately. | + +----------------------------------------------------------------------+ + | Author: Florian Engelhardt | + +----------------------------------------------------------------------+ +*/ + +#include "php.h" +#include "php_test.h" +#include "Zend/zend_alloc.h" +#include "zend_portability.h" +#include +#include + +void* observe_malloc(size_t size ZEND_FILE_LINE_DC ZEND_FILE_LINE_ORIG_DC) +{ + void *ptr = NULL; + if (ZT_G(custom_malloc)) { + zend_mm_set_heap(ZT_G(original_heap)); + ptr = ZT_G(custom_malloc)(size ZEND_FILE_LINE_RELAY_CC ZEND_FILE_LINE_ORIG_RELAY_CC); + zend_mm_set_heap(ZT_G(observed_heap)); + } else { + ptr = _zend_mm_alloc(ZT_G(original_heap), size ZEND_FILE_LINE_RELAY_CC ZEND_FILE_LINE_ORIG_RELAY_CC); + } + printf("Allocated %zu bytes at %p\n", size, ptr); + return ptr; +} + +void observe_free(void* ptr ZEND_FILE_LINE_DC ZEND_FILE_LINE_ORIG_DC) +{ + if (ZT_G(custom_free)) + { + zend_mm_set_heap(ZT_G(original_heap)); + ZT_G(custom_free)(ptr ZEND_FILE_LINE_RELAY_CC ZEND_FILE_LINE_ORIG_RELAY_CC); + zend_mm_set_heap(ZT_G(observed_heap)); + } else { + _zend_mm_free(ZT_G(original_heap), ptr ZEND_FILE_LINE_RELAY_CC ZEND_FILE_LINE_ORIG_RELAY_CC); + } + printf("Freed memory at %p\n", ptr); +} + +void* observe_realloc(void* ptr, size_t size ZEND_FILE_LINE_DC ZEND_FILE_LINE_ORIG_DC) +{ + void * new_ptr; + if (ZT_G(custom_realloc)) + { + zend_mm_set_heap(ZT_G(original_heap)); + new_ptr = ZT_G(custom_realloc)(ptr, size ZEND_FILE_LINE_RELAY_CC ZEND_FILE_LINE_ORIG_RELAY_CC); + zend_mm_set_heap(ZT_G(observed_heap)); + } else { + new_ptr = _zend_mm_realloc(ZT_G(original_heap), ptr, size ZEND_FILE_LINE_RELAY_CC ZEND_FILE_LINE_ORIG_RELAY_CC); + } + printf("Realloc of %zu bytes from %p to %p\n", size, ptr, new_ptr); + return new_ptr; +} + +size_t observe_gc(void) +{ + size_t size = 0; + if (ZT_G(custom_gc)) { + zend_mm_set_heap(ZT_G(original_heap)); + size = ZT_G(custom_gc)(); + zend_mm_set_heap(ZT_G(observed_heap)); + } else { + size = zend_mm_gc(ZT_G(original_heap)); + } + printf("ZendMM GC freed %zu bytes", size); + return size; +} + +void observe_shutdown(bool full, bool silent) +{ + if (ZT_G(custom_shutdown)) { + zend_mm_set_heap(ZT_G(original_heap)); + ZT_G(custom_shutdown)(full, silent); + zend_mm_set_heap(ZT_G(observed_heap)); + } else { + zend_mm_shutdown(ZT_G(original_heap), full, silent); + } + printf("Shutdown happened: full -> %d, silent -> %d\n", full, silent); +} + +void zend_test_mm_custom_handlers_init(void) +{ + if (ZT_G(observed_heap) != NULL) { + return; + } + ZT_G(original_heap) = zend_mm_get_heap(); + if (zend_mm_is_custom_heap(ZT_G(original_heap))) { + zend_mm_get_custom_handlers( + ZT_G(original_heap), + &ZT_G(custom_malloc), + &ZT_G(custom_free), + &ZT_G(custom_realloc), + &ZT_G(custom_gc), + &ZT_G(custom_shutdown) + ); + } + printf("Prev handlers at %p, %p, %p, %p, %p\n", ZT_G(custom_malloc), ZT_G(custom_free), ZT_G(custom_realloc), ZT_G(custom_gc), ZT_G(custom_shutdown)); + ZT_G(observed_heap) = zend_mm_heap_create(); + zend_mm_set_custom_handlers( + ZT_G(observed_heap), + observe_malloc, + observe_free, + observe_realloc, + observe_gc, + observe_shutdown + ); + zend_mm_set_heap(ZT_G(observed_heap)); + printf("Heap at %p installed in ZendMM (orig at %p)\n", ZT_G(observed_heap), ZT_G(original_heap)); +} + +void zend_test_mm_custom_handlers_shutdown(void) +{ + if (ZT_G(observed_heap) == NULL) { + return; + } + zend_mm_set_heap(ZT_G(original_heap)); + zend_mm_heap_free(ZT_G(observed_heap)); + ZT_G(observed_heap) = NULL; + printf("Prev heap at %p restored in ZendMM\n", ZT_G(original_heap)); +} + +void zend_test_mm_custom_handlers_rshutdown(void) +{ + zend_test_mm_custom_handlers_shutdown(); +} + +void zend_test_mm_custom_handlers_rinit(void) +{ + if (ZT_G(zend_mm_custom_handlers_enabled)) { + zend_test_mm_custom_handlers_init(); + } +} + +static PHP_INI_MH(OnUpdateZendTestMMCustomHandlersEnabled) +{ + if (new_value == NULL) { + return FAILURE; + } + + int int_value = zend_ini_parse_bool(new_value); + + if (int_value == 1) { + zend_test_mm_custom_handlers_init(); + } else { + zend_test_mm_custom_handlers_shutdown(); + } + return OnUpdateBool(entry, new_value, mh_arg1, mh_arg2, mh_arg3, stage); +} + +PHP_INI_BEGIN() + STD_PHP_INI_BOOLEAN("zend_test.zend_mm_custom_handlers.enabled", "0", PHP_INI_USER, OnUpdateZendTestMMCustomHandlersEnabled, zend_mm_custom_handlers_enabled, zend_zend_test_globals, zend_test_globals) +PHP_INI_END() + +void zend_test_mm_custom_handlers_minit(INIT_FUNC_ARGS) +{ + if (type != MODULE_TEMPORARY) { + REGISTER_INI_ENTRIES(); + } else { + (void)ini_entries; + } +} diff --git a/ext/zend_test/zend_mm_custom_handlers.h b/ext/zend_test/zend_mm_custom_handlers.h new file mode 100644 index 0000000000000..7e0c8021e7e22 --- /dev/null +++ b/ext/zend_test/zend_mm_custom_handlers.h @@ -0,0 +1,24 @@ +/* + +----------------------------------------------------------------------+ + | Copyright (c) The PHP Group | + +----------------------------------------------------------------------+ + | This source file is subject to version 3.01 of the PHP license, | + | that is bundled with this package in the file LICENSE, and is | + | available through the world-wide-web at the following url: | + | https://www.php.net/license/3_01.txt | + | If you did not receive a copy of the PHP license and are unable to | + | obtain it through the world-wide-web, please send a note to | + | license@php.net so we can mail you a copy immediately. | + +----------------------------------------------------------------------+ + | Author: Florian Engelhardt | + +----------------------------------------------------------------------+ +*/ + +#ifndef ZEND_TEST_MM_CUSTOM_HANDLERS_H +#define ZEND_TEST_MM_CUSTOM_HANDLERS_H + +void zend_test_mm_custom_handlers_minit(INIT_FUNC_ARGS); +void zend_test_mm_custom_handlers_rinit(void); +void zend_test_mm_custom_handlers_rshutdown(void); + +#endif diff --git a/sapi/phpdbg/phpdbg.c b/sapi/phpdbg/phpdbg.c index 9811f750b0f6e..369b87a1441f1 100644 --- a/sapi/phpdbg/phpdbg.c +++ b/sapi/phpdbg/phpdbg.c @@ -1404,7 +1404,7 @@ int main(int argc, char **argv) /* {{{ */ #endif mm_heap = zend_mm_get_heap(); - zend_mm_get_custom_handlers(mm_heap, &_malloc, &_free, &_realloc); + zend_mm_get_custom_handlers(mm_heap, &_malloc, &_free, &_realloc, NULL, NULL); use_mm_wrappers = !_malloc && !_realloc && !_free; @@ -1412,9 +1412,9 @@ int main(int argc, char **argv) /* {{{ */ _free = phpdbg_watch_efree; if (use_mm_wrappers) { - zend_mm_set_custom_handlers(mm_heap, phpdbg_malloc_wrapper, phpdbg_free_wrapper, phpdbg_realloc_wrapper); + zend_mm_set_custom_handlers(mm_heap, phpdbg_malloc_wrapper, phpdbg_free_wrapper, phpdbg_realloc_wrapper, NULL, NULL); } else { - zend_mm_set_custom_handlers(mm_heap, _malloc, _free, _realloc); + zend_mm_set_custom_handlers(mm_heap, _malloc, _free, _realloc, NULL, NULL); } _free = PHPDBG_G(original_free_function); @@ -1759,7 +1759,7 @@ int main(int argc, char **argv) /* {{{ */ #ifdef ZTS /* reset to original handlers - otherwise PHPDBG_G() in phpdbg_watch_efree will be segfaulty (with e.g. USE_ZEND_ALLOC=0) */ if (!use_mm_wrappers) { - zend_mm_set_custom_handlers(zend_mm_get_heap(), _malloc, _free, _realloc); + zend_mm_set_custom_handlers(zend_mm_get_heap(), _malloc, _free, _realloc, NULL, NULL); } ts_free_id(phpdbg_globals_id); From 126493e0cda618cdc4960233e419b38bd108a478 Mon Sep 17 00:00:00 2001 From: Florian Engelhardt Date: Mon, 17 Jun 2024 08:13:29 +0200 Subject: [PATCH 2/4] remove redundant `zend_mm_heap_create()` function --- Zend/zend_alloc.c | 5 ----- Zend/zend_alloc.h | 1 - ext/zend_test/zend_mm_custom_handlers.c | 2 +- 3 files changed, 1 insertion(+), 7 deletions(-) diff --git a/Zend/zend_alloc.c b/Zend/zend_alloc.c index c69ff5759beeb..59b793c585d8a 100644 --- a/Zend/zend_alloc.c +++ b/Zend/zend_alloc.c @@ -3137,11 +3137,6 @@ ZEND_API zend_mm_heap *zend_mm_get_heap(void) return AG(mm_heap); } -ZEND_API zend_mm_heap *zend_mm_heap_create(void) -{ - return zend_mm_init(); -} - ZEND_API void zend_mm_heap_free(zend_mm_heap *heap) { zend_mm_chunk_free(heap, heap->main_chunk, ZEND_MM_CHUNK_SIZE); diff --git a/Zend/zend_alloc.h b/Zend/zend_alloc.h index ea91228482e46..46e235b27d565 100644 --- a/Zend/zend_alloc.h +++ b/Zend/zend_alloc.h @@ -263,7 +263,6 @@ ZEND_API size_t ZEND_FASTCALL _zend_mm_block_size(zend_mm_heap *heap, void *p ZE #define zend_mm_realloc2_rel(heap, p, size, copy_size) _zend_mm_realloc2((heap), (p), (size), (copy_size) ZEND_FILE_LINE_RELAY_CC ZEND_FILE_LINE_CC) #define zend_mm_block_size_rel(heap, p) _zend_mm_block_size((heap), (p) ZEND_FILE_LINE_CC ZEND_FILE_LINE_EMPTY_CC) -ZEND_API zend_mm_heap *zend_mm_heap_create(void); ZEND_API void zend_mm_heap_free(zend_mm_heap* heap); ZEND_API zend_mm_heap *zend_mm_set_heap(zend_mm_heap *new_heap); ZEND_API zend_mm_heap *zend_mm_get_heap(void); diff --git a/ext/zend_test/zend_mm_custom_handlers.c b/ext/zend_test/zend_mm_custom_handlers.c index db178ac3ae705..9f696f1b7592e 100644 --- a/ext/zend_test/zend_mm_custom_handlers.c +++ b/ext/zend_test/zend_mm_custom_handlers.c @@ -106,7 +106,7 @@ void zend_test_mm_custom_handlers_init(void) ); } printf("Prev handlers at %p, %p, %p, %p, %p\n", ZT_G(custom_malloc), ZT_G(custom_free), ZT_G(custom_realloc), ZT_G(custom_gc), ZT_G(custom_shutdown)); - ZT_G(observed_heap) = zend_mm_heap_create(); + ZT_G(observed_heap) = zend_mm_startup(); zend_mm_set_custom_handlers( ZT_G(observed_heap), observe_malloc, From 06ef9d59cec2ba66fd7400ead98b391f7934e3ab Mon Sep 17 00:00:00 2001 From: Florian Engelhardt Date: Mon, 17 Jun 2024 08:20:34 +0200 Subject: [PATCH 3/4] drop redundant `zend_mm_heap_free()` --- Zend/zend_alloc.c | 5 ----- Zend/zend_alloc.h | 1 - ext/zend_test/zend_mm_custom_handlers.c | 10 +++++++++- 3 files changed, 9 insertions(+), 7 deletions(-) diff --git a/Zend/zend_alloc.c b/Zend/zend_alloc.c index 59b793c585d8a..fd97e56c7702d 100644 --- a/Zend/zend_alloc.c +++ b/Zend/zend_alloc.c @@ -3137,11 +3137,6 @@ ZEND_API zend_mm_heap *zend_mm_get_heap(void) return AG(mm_heap); } -ZEND_API void zend_mm_heap_free(zend_mm_heap *heap) -{ - zend_mm_chunk_free(heap, heap->main_chunk, ZEND_MM_CHUNK_SIZE); -} - ZEND_API bool zend_mm_is_custom_heap(zend_mm_heap *new_heap) { #if ZEND_MM_CUSTOM diff --git a/Zend/zend_alloc.h b/Zend/zend_alloc.h index 46e235b27d565..023b1613c65ce 100644 --- a/Zend/zend_alloc.h +++ b/Zend/zend_alloc.h @@ -263,7 +263,6 @@ ZEND_API size_t ZEND_FASTCALL _zend_mm_block_size(zend_mm_heap *heap, void *p ZE #define zend_mm_realloc2_rel(heap, p, size, copy_size) _zend_mm_realloc2((heap), (p), (size), (copy_size) ZEND_FILE_LINE_RELAY_CC ZEND_FILE_LINE_CC) #define zend_mm_block_size_rel(heap, p) _zend_mm_block_size((heap), (p) ZEND_FILE_LINE_CC ZEND_FILE_LINE_EMPTY_CC) -ZEND_API void zend_mm_heap_free(zend_mm_heap* heap); ZEND_API zend_mm_heap *zend_mm_set_heap(zend_mm_heap *new_heap); ZEND_API zend_mm_heap *zend_mm_get_heap(void); diff --git a/ext/zend_test/zend_mm_custom_handlers.c b/ext/zend_test/zend_mm_custom_handlers.c index 9f696f1b7592e..6da197734b451 100644 --- a/ext/zend_test/zend_mm_custom_handlers.c +++ b/ext/zend_test/zend_mm_custom_handlers.c @@ -125,7 +125,15 @@ void zend_test_mm_custom_handlers_shutdown(void) return; } zend_mm_set_heap(ZT_G(original_heap)); - zend_mm_heap_free(ZT_G(observed_heap)); + zend_mm_set_custom_handlers( + ZT_G(observed_heap), + NULL, + NULL, + NULL, + NULL, + NULL + ); + zend_mm_shutdown(ZT_G(observed_heap), true, true); ZT_G(observed_heap) = NULL; printf("Prev heap at %p restored in ZendMM\n", ZT_G(original_heap)); } From 32ddb428c2e924cc345483b8d4c245aadf09b924 Mon Sep 17 00:00:00 2001 From: Florian Engelhardt Date: Wed, 19 Jun 2024 16:07:23 +0200 Subject: [PATCH 4/4] make `zend_mm_set_custom_handlers_ex()` --- Zend/zend_alloc.c | 30 ++++++++++++++++++++----- Zend/zend_alloc.h | 14 +++++++++--- ext/zend_test/test.c | 4 +--- ext/zend_test/zend_mm_custom_handlers.c | 6 ++--- sapi/phpdbg/phpdbg.c | 8 +++---- 5 files changed, 44 insertions(+), 18 deletions(-) diff --git a/Zend/zend_alloc.c b/Zend/zend_alloc.c index fd97e56c7702d..626bbe7b31b34 100644 --- a/Zend/zend_alloc.c +++ b/Zend/zend_alloc.c @@ -3147,6 +3147,16 @@ ZEND_API bool zend_mm_is_custom_heap(zend_mm_heap *new_heap) } ZEND_API void zend_mm_set_custom_handlers(zend_mm_heap *heap, + void* (*_malloc)(size_t ZEND_FILE_LINE_DC ZEND_FILE_LINE_ORIG_DC), + void (*_free)(void* ZEND_FILE_LINE_DC ZEND_FILE_LINE_ORIG_DC), + void* (*_realloc)(void*, size_t ZEND_FILE_LINE_DC ZEND_FILE_LINE_ORIG_DC)) +{ +#if ZEND_MM_CUSTOM + zend_mm_set_custom_handlers_ex(heap, _malloc, _free, _realloc, NULL, NULL); +#endif +} + +ZEND_API void zend_mm_set_custom_handlers_ex(zend_mm_heap *heap, void* (*_malloc)(size_t ZEND_FILE_LINE_DC ZEND_FILE_LINE_ORIG_DC), void (*_free)(void* ZEND_FILE_LINE_DC ZEND_FILE_LINE_ORIG_DC), void* (*_realloc)(void*, size_t ZEND_FILE_LINE_DC ZEND_FILE_LINE_ORIG_DC), @@ -3170,11 +3180,21 @@ ZEND_API void zend_mm_set_custom_handlers(zend_mm_heap *heap, } ZEND_API void zend_mm_get_custom_handlers(zend_mm_heap *heap, - void* (**_malloc)(size_t ZEND_FILE_LINE_DC ZEND_FILE_LINE_ORIG_DC), - void (**_free)(void* ZEND_FILE_LINE_DC ZEND_FILE_LINE_ORIG_DC), - void* (**_realloc)(void*, size_t ZEND_FILE_LINE_DC ZEND_FILE_LINE_ORIG_DC), - size_t (**_gc)(void), - void (**_shutdown)(bool, bool)) + void* (**_malloc)(size_t ZEND_FILE_LINE_DC ZEND_FILE_LINE_ORIG_DC), + void (**_free)(void* ZEND_FILE_LINE_DC ZEND_FILE_LINE_ORIG_DC), + void* (**_realloc)(void*, size_t ZEND_FILE_LINE_DC ZEND_FILE_LINE_ORIG_DC)) +{ +#if ZEND_MM_CUSTOM + zend_mm_get_custom_handlers_ex(heap, _malloc, _free, _realloc, NULL, NULL); +#endif +} + +ZEND_API void zend_mm_get_custom_handlers_ex(zend_mm_heap *heap, + void* (**_malloc)(size_t ZEND_FILE_LINE_DC ZEND_FILE_LINE_ORIG_DC), + void (**_free)(void* ZEND_FILE_LINE_DC ZEND_FILE_LINE_ORIG_DC), + void* (**_realloc)(void*, size_t ZEND_FILE_LINE_DC ZEND_FILE_LINE_ORIG_DC), + size_t (**_gc)(void), + void (**_shutdown)(bool, bool)) { #if ZEND_MM_CUSTOM zend_mm_heap *_heap = (zend_mm_heap*)heap; diff --git a/Zend/zend_alloc.h b/Zend/zend_alloc.h index 023b1613c65ce..541989a2a13e0 100644 --- a/Zend/zend_alloc.h +++ b/Zend/zend_alloc.h @@ -276,10 +276,18 @@ ZEND_API bool zend_mm_is_custom_heap(zend_mm_heap *new_heap); ZEND_API void zend_mm_set_custom_handlers(zend_mm_heap *heap, void* (*_malloc)(size_t ZEND_FILE_LINE_DC ZEND_FILE_LINE_ORIG_DC), void (*_free)(void* ZEND_FILE_LINE_DC ZEND_FILE_LINE_ORIG_DC), - void* (*_realloc)(void*, size_t ZEND_FILE_LINE_DC ZEND_FILE_LINE_ORIG_DC), - size_t (*_gc)(void), - void (*_shutdown)(bool, bool)); + void* (*_realloc)(void*, size_t ZEND_FILE_LINE_DC ZEND_FILE_LINE_ORIG_DC)); +ZEND_API void zend_mm_set_custom_handlers_ex(zend_mm_heap *heap, + void* (*_malloc)(size_t ZEND_FILE_LINE_DC ZEND_FILE_LINE_ORIG_DC), + void (*_free)(void* ZEND_FILE_LINE_DC ZEND_FILE_LINE_ORIG_DC), + void* (*_realloc)(void*, size_t ZEND_FILE_LINE_DC ZEND_FILE_LINE_ORIG_DC), + size_t (*_gc)(void), + void (*_shutdown)(bool, bool)); ZEND_API void zend_mm_get_custom_handlers(zend_mm_heap *heap, + void* (**_malloc)(size_t ZEND_FILE_LINE_DC ZEND_FILE_LINE_ORIG_DC), + void (**_free)(void* ZEND_FILE_LINE_DC ZEND_FILE_LINE_ORIG_DC), + void* (**_realloc)(void*, size_t ZEND_FILE_LINE_DC ZEND_FILE_LINE_ORIG_DC)); +ZEND_API void zend_mm_get_custom_handlers_ex(zend_mm_heap *heap, void* (**_malloc)(size_t ZEND_FILE_LINE_DC ZEND_FILE_LINE_ORIG_DC), void (**_free)(void* ZEND_FILE_LINE_DC ZEND_FILE_LINE_ORIG_DC), void* (**_realloc)(void*, size_t ZEND_FILE_LINE_DC ZEND_FILE_LINE_ORIG_DC), diff --git a/ext/zend_test/test.c b/ext/zend_test/test.c index 00ecd66c7df4e..bdd97d69908da 100644 --- a/ext/zend_test/test.c +++ b/ext/zend_test/test.c @@ -709,9 +709,7 @@ static PHP_INI_MH(OnUpdateZendTestObserveOplineInZendMM) ZT_G(zend_test_heap), zend_test_custom_malloc, zend_test_custom_free, - zend_test_custom_realloc, - NULL, - NULL + zend_test_custom_realloc ); ZT_G(zend_orig_heap) = zend_mm_get_heap(); zend_mm_set_heap(ZT_G(zend_test_heap)); diff --git a/ext/zend_test/zend_mm_custom_handlers.c b/ext/zend_test/zend_mm_custom_handlers.c index 6da197734b451..2130065109efa 100644 --- a/ext/zend_test/zend_mm_custom_handlers.c +++ b/ext/zend_test/zend_mm_custom_handlers.c @@ -96,7 +96,7 @@ void zend_test_mm_custom_handlers_init(void) } ZT_G(original_heap) = zend_mm_get_heap(); if (zend_mm_is_custom_heap(ZT_G(original_heap))) { - zend_mm_get_custom_handlers( + zend_mm_get_custom_handlers_ex( ZT_G(original_heap), &ZT_G(custom_malloc), &ZT_G(custom_free), @@ -107,7 +107,7 @@ void zend_test_mm_custom_handlers_init(void) } printf("Prev handlers at %p, %p, %p, %p, %p\n", ZT_G(custom_malloc), ZT_G(custom_free), ZT_G(custom_realloc), ZT_G(custom_gc), ZT_G(custom_shutdown)); ZT_G(observed_heap) = zend_mm_startup(); - zend_mm_set_custom_handlers( + zend_mm_set_custom_handlers_ex( ZT_G(observed_heap), observe_malloc, observe_free, @@ -125,7 +125,7 @@ void zend_test_mm_custom_handlers_shutdown(void) return; } zend_mm_set_heap(ZT_G(original_heap)); - zend_mm_set_custom_handlers( + zend_mm_set_custom_handlers_ex( ZT_G(observed_heap), NULL, NULL, diff --git a/sapi/phpdbg/phpdbg.c b/sapi/phpdbg/phpdbg.c index 369b87a1441f1..9811f750b0f6e 100644 --- a/sapi/phpdbg/phpdbg.c +++ b/sapi/phpdbg/phpdbg.c @@ -1404,7 +1404,7 @@ int main(int argc, char **argv) /* {{{ */ #endif mm_heap = zend_mm_get_heap(); - zend_mm_get_custom_handlers(mm_heap, &_malloc, &_free, &_realloc, NULL, NULL); + zend_mm_get_custom_handlers(mm_heap, &_malloc, &_free, &_realloc); use_mm_wrappers = !_malloc && !_realloc && !_free; @@ -1412,9 +1412,9 @@ int main(int argc, char **argv) /* {{{ */ _free = phpdbg_watch_efree; if (use_mm_wrappers) { - zend_mm_set_custom_handlers(mm_heap, phpdbg_malloc_wrapper, phpdbg_free_wrapper, phpdbg_realloc_wrapper, NULL, NULL); + zend_mm_set_custom_handlers(mm_heap, phpdbg_malloc_wrapper, phpdbg_free_wrapper, phpdbg_realloc_wrapper); } else { - zend_mm_set_custom_handlers(mm_heap, _malloc, _free, _realloc, NULL, NULL); + zend_mm_set_custom_handlers(mm_heap, _malloc, _free, _realloc); } _free = PHPDBG_G(original_free_function); @@ -1759,7 +1759,7 @@ int main(int argc, char **argv) /* {{{ */ #ifdef ZTS /* reset to original handlers - otherwise PHPDBG_G() in phpdbg_watch_efree will be segfaulty (with e.g. USE_ZEND_ALLOC=0) */ if (!use_mm_wrappers) { - zend_mm_set_custom_handlers(zend_mm_get_heap(), _malloc, _free, _realloc, NULL, NULL); + zend_mm_set_custom_handlers(zend_mm_get_heap(), _malloc, _free, _realloc); } ts_free_id(phpdbg_globals_id);