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.

Closes GH-16602.
This commit is contained in:
Niels Dossche 2024-10-25 20:34:20 +02:00
parent d6839f77ee
commit 757781a142
No known key found for this signature in database
GPG key ID: B8A8AD166DF0E2E5
4 changed files with 30 additions and 0 deletions

2
NEWS
View file

@ -5,6 +5,8 @@ PHP NEWS
- Core:
. Fixed bug GH-16574 (Incorrect error "undefined method" messages).
(nielsdos)
. Fixed bug GH-16577 (EG(strtod_state).freelist leaks with opcache.preload).
(nielsdos)
- GD:
. Fixed bug GH-16559 (UBSan abort in ext/gd/libgd/gd_interpolation.c:1007).

View file

@ -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));

View file

@ -0,0 +1,2 @@
<?php
var_dump(1.5);

View file

@ -0,0 +1,20 @@
--TEST--
GH-16577 (EG(strtod_state).freelist leaks with opcache.preload)
--INI--
opcache.enable=1
opcache.enable_cli=1
opcache.optimization_level=-1
opcache.preload={PWD}/gh16577.inc
--EXTENSIONS--
opcache
--SKIPIF--
<?php
if (PHP_OS_FAMILY == 'Windows') die('skip Preloading is not supported on Windows');
?>
--FILE--
<?php
echo "Done\n";
?>
--EXPECT--
float(1.5)
Done