From 4248bfd4535a820959406813db0581e6e45a62e8 Mon Sep 17 00:00:00 2001 From: Niels Dossche <7771979+nielsdos@users.noreply.github.com> Date: Fri, 25 Oct 2024 20:34:20 +0200 Subject: [PATCH] Fix GH-16577: EG(strtod_state).freelist leaks with opcache.preload This happens because on ZTS we execute `executor_globals_ctor` which reset the `freelist` and `p5s` pointers, while on NTS we don't. On NTS we can reuse the caches but on ZTS we can't, the easiest fix is to call `zend_shutdown_strtod` when preloading is shut down. This regressed in GH-13974 and therefore only exists in PHP 8.4 and higher. --- ext/opcache/ZendAccelerator.c | 6 ++++++ ext/opcache/tests/gh16577.inc | 2 ++ ext/opcache/tests/gh16577.phpt | 20 ++++++++++++++++++++ 3 files changed, 28 insertions(+) create mode 100644 ext/opcache/tests/gh16577.inc create mode 100644 ext/opcache/tests/gh16577.phpt diff --git a/ext/opcache/ZendAccelerator.c b/ext/opcache/ZendAccelerator.c index 3e8bdea9c7a6..e0f8cda2298e 100644 --- a/ext/opcache/ZendAccelerator.c +++ b/ext/opcache/ZendAccelerator.c @@ -4462,6 +4462,12 @@ static zend_result accel_preload(const char *config, bool in_child) /* Release stored values to avoid dangling pointers */ zend_shutdown_executor_values(/* fast_shutdown */ false); + /* On ZTS we execute `executor_globals_ctor` which reset the freelist and p5s pointers, while on NTS we don't. + * We have to clean up the memory before the actual request takes place to avoid a memory leak. */ +#ifdef ZTS + zend_shutdown_strtod(); +#endif + /* We don't want to preload constants. * Check that zend_shutdown_executor_values() also destroys constants. */ ZEND_ASSERT(zend_hash_num_elements(EG(zend_constants)) == EG(persistent_constants_count)); diff --git a/ext/opcache/tests/gh16577.inc b/ext/opcache/tests/gh16577.inc new file mode 100644 index 000000000000..f016d6128178 --- /dev/null +++ b/ext/opcache/tests/gh16577.inc @@ -0,0 +1,2 @@ + +--FILE-- + +--EXPECT-- +float(1.5) +Done