mirror of
https://github.com/php/php-src.git
synced 2025-08-16 05:58:45 +02:00
Merge branch 'PHP-8.2'
* PHP-8.2: Re-add some CTE functions that were removed from being CTE by a mistake Fix GH-8065: opcache.consistency_checks > 0 causes segfaults in PHP >= 8.1.5 in fpm context Fix GH-8646: Memory leak PHP FPM 8.1
This commit is contained in:
commit
b39ff334a3
11 changed files with 151 additions and 12 deletions
28
Zend/zend.c
28
Zend/zend.c
|
@ -1281,6 +1281,34 @@ ZEND_API void zend_deactivate(void) /* {{{ */
|
|||
|
||||
zend_destroy_rsrc_list(&EG(regular_list));
|
||||
|
||||
/* See GH-8646: https://github.com/php/php-src/issues/8646
|
||||
*
|
||||
* Interned strings that hold class entries can get a corresponding slot in map_ptr for the CE cache.
|
||||
* map_ptr works like a bump allocator: there is a counter which increases to allocate the next slot in the map.
|
||||
*
|
||||
* For class name strings in non-opcache we have:
|
||||
* - on startup: permanent + interned
|
||||
* - on request: interned
|
||||
* For class name strings in opcache we have:
|
||||
* - on startup: permanent + interned
|
||||
* - on request: either not interned at all, which we can ignore because they won't get a CE cache entry
|
||||
* or they were already permanent + interned
|
||||
* or we get a new permanent + interned string in the opcache persistence code
|
||||
*
|
||||
* Notice that the map_ptr layout always has the permanent strings first, and the request strings after.
|
||||
* In non-opcache, a request string may get a slot in map_ptr, and that interned request string
|
||||
* gets destroyed at the end of the request. The corresponding map_ptr slot can thereafter never be used again.
|
||||
* This causes map_ptr to keep reallocating to larger and larger sizes.
|
||||
*
|
||||
* We solve it as follows:
|
||||
* We can check whether we had any interned request strings, which only happens in non-opcache.
|
||||
* If we have any, we reset map_ptr to the last permanent string.
|
||||
* We can't lose any permanent strings because of map_ptr's layout.
|
||||
*/
|
||||
if (zend_hash_num_elements(&CG(interned_strings)) > 0) {
|
||||
zend_map_ptr_reset();
|
||||
}
|
||||
|
||||
#if GC_BENCH
|
||||
fprintf(stderr, "GC Statistics\n");
|
||||
fprintf(stderr, "-------------\n");
|
||||
|
|
|
@ -541,6 +541,7 @@ function imagesetbrush(GdImage $image, GdImage $brush): bool {}
|
|||
/** @refcount 1 */
|
||||
function imagecreate(int $width, int $height): GdImage|false {}
|
||||
|
||||
/** @compile-time-eval */
|
||||
function imagetypes(): int {}
|
||||
|
||||
/** @refcount 1 */
|
||||
|
|
4
ext/gd/gd_arginfo.h
generated
4
ext/gd/gd_arginfo.h
generated
|
@ -1,5 +1,5 @@
|
|||
/* This is a generated file, edit the .stub.php file instead.
|
||||
* Stub hash: 81ba6bf7b07027f6930db1c48a602f27724958af */
|
||||
* Stub hash: 810838932a482065c48ab715857062c071db31fd */
|
||||
|
||||
ZEND_BEGIN_ARG_WITH_RETURN_TYPE_INFO_EX(arginfo_gd_info, 0, 0, IS_ARRAY, 0)
|
||||
ZEND_END_ARG_INFO()
|
||||
|
@ -747,7 +747,7 @@ static const zend_function_entry ext_functions[] = {
|
|||
ZEND_FE(imagesettile, arginfo_imagesettile)
|
||||
ZEND_FE(imagesetbrush, arginfo_imagesetbrush)
|
||||
ZEND_FE(imagecreate, arginfo_imagecreate)
|
||||
ZEND_FE(imagetypes, arginfo_imagetypes)
|
||||
ZEND_SUPPORTS_COMPILE_TIME_EVAL_FE(imagetypes, arginfo_imagetypes)
|
||||
ZEND_FE(imagecreatefromstring, arginfo_imagecreatefromstring)
|
||||
#if defined(HAVE_GD_AVIF)
|
||||
ZEND_FE(imagecreatefromavif, arginfo_imagecreatefromavif)
|
||||
|
|
26
ext/opcache/tests/gh8065.phpt
Normal file
26
ext/opcache/tests/gh8065.phpt
Normal file
|
@ -0,0 +1,26 @@
|
|||
--TEST--
|
||||
GH-8065: opcache.consistency_checks > 0 causes segfaults in PHP >= 8.1.5 in fpm context
|
||||
--EXTENSIONS--
|
||||
opcache
|
||||
--INI--
|
||||
opcache.enable_cli=1
|
||||
opcache.consistency_checks=1
|
||||
opcache.log_verbosity_level=2
|
||||
--FILE--
|
||||
<?php
|
||||
var_dump(ini_get("opcache.consistency_checks"));
|
||||
var_dump(ini_set("opcache.consistency_checks", 1));
|
||||
var_dump(ini_set("opcache.consistency_checks", -1));
|
||||
var_dump(ini_set("opcache.consistency_checks", 0));
|
||||
?>
|
||||
--EXPECTF--
|
||||
%sWarning opcache.consistency_checks is reset back to 0 because it does not work properly (see GH-8065, GH-10624).
|
||||
|
||||
string(1) "0"
|
||||
%sWarning opcache.consistency_checks is reset back to 0 because it does not work properly (see GH-8065, GH-10624).
|
||||
|
||||
bool(false)
|
||||
%sWarning opcache.consistency_checks is reset back to 0 because it does not work properly (see GH-8065, GH-10624).
|
||||
|
||||
bool(false)
|
||||
string(1) "0"
|
|
@ -129,6 +129,19 @@ static ZEND_INI_MH(OnUpdateMaxWastedPercentage)
|
|||
return SUCCESS;
|
||||
}
|
||||
|
||||
static ZEND_INI_MH(OnUpdateConsistencyChecks)
|
||||
{
|
||||
zend_long *p = (zend_long *) ZEND_INI_GET_ADDR();
|
||||
zend_long consistency_checks = atoi(ZSTR_VAL(new_value));
|
||||
|
||||
if (consistency_checks != 0) {
|
||||
zend_accel_error(ACCEL_LOG_WARNING, "opcache.consistency_checks is reset back to 0 because it does not work properly (see GH-8065, GH-10624).\n");
|
||||
return FAILURE;
|
||||
}
|
||||
*p = 0;
|
||||
return SUCCESS;
|
||||
}
|
||||
|
||||
static ZEND_INI_MH(OnEnable)
|
||||
{
|
||||
if (stage == ZEND_INI_STAGE_STARTUP ||
|
||||
|
@ -263,7 +276,7 @@ ZEND_INI_BEGIN()
|
|||
STD_PHP_INI_ENTRY("opcache.interned_strings_buffer", "8" , PHP_INI_SYSTEM, OnUpdateInternedStringsBuffer, accel_directives.interned_strings_buffer, zend_accel_globals, accel_globals)
|
||||
STD_PHP_INI_ENTRY("opcache.max_accelerated_files" , "10000", PHP_INI_SYSTEM, OnUpdateMaxAcceleratedFiles, accel_directives.max_accelerated_files, zend_accel_globals, accel_globals)
|
||||
STD_PHP_INI_ENTRY("opcache.max_wasted_percentage" , "5" , PHP_INI_SYSTEM, OnUpdateMaxWastedPercentage, accel_directives.max_wasted_percentage, zend_accel_globals, accel_globals)
|
||||
STD_PHP_INI_ENTRY("opcache.consistency_checks" , "0" , PHP_INI_ALL , OnUpdateLong, accel_directives.consistency_checks, zend_accel_globals, accel_globals)
|
||||
STD_PHP_INI_ENTRY("opcache.consistency_checks" , "0" , PHP_INI_ALL , OnUpdateConsistencyChecks, accel_directives.consistency_checks, zend_accel_globals, accel_globals)
|
||||
STD_PHP_INI_ENTRY("opcache.force_restart_timeout" , "180" , PHP_INI_SYSTEM, OnUpdateLong, accel_directives.force_restart_timeout, zend_accel_globals, accel_globals)
|
||||
STD_PHP_INI_ENTRY("opcache.revalidate_freq" , "2" , PHP_INI_ALL , OnUpdateLong, accel_directives.revalidate_freq, zend_accel_globals, accel_globals)
|
||||
STD_PHP_INI_ENTRY("opcache.file_update_protection", "2" , PHP_INI_ALL , OnUpdateLong, accel_directives.file_update_protection, zend_accel_globals, accel_globals)
|
||||
|
|
|
@ -1846,7 +1846,10 @@ function array_filter(array $array, ?callable $callback = null, int $mode = 0):
|
|||
|
||||
function array_map(?callable $callback, array $array, array ...$arrays): array {}
|
||||
|
||||
/** @param string|int $key */
|
||||
/**
|
||||
* @param string|int $key
|
||||
* @compile-time-eval
|
||||
*/
|
||||
function array_key_exists($key, array $array): bool {}
|
||||
|
||||
/**
|
||||
|
@ -1859,6 +1862,7 @@ function array_chunk(array $array, int $length, bool $preserve_keys = false): ar
|
|||
|
||||
function array_combine(array $keys, array $values): array {}
|
||||
|
||||
/** @compile-time-eval */
|
||||
function array_is_list(array $array): bool {}
|
||||
|
||||
/* base64.c */
|
||||
|
@ -2314,7 +2318,10 @@ function pathinfo(string $path, int $flags = PATHINFO_ALL): array|string {}
|
|||
/** @refcount 1 */
|
||||
function stristr(string $haystack, string $needle, bool $before_needle = false): string|false {}
|
||||
|
||||
/** @refcount 1 */
|
||||
/**
|
||||
* @compile-time-eval
|
||||
* @refcount 1
|
||||
*/
|
||||
function strstr(string $haystack, string $needle, bool $before_needle = false): string|false {}
|
||||
|
||||
/** @alias strstr */
|
||||
|
|
8
ext/standard/basic_functions_arginfo.h
generated
8
ext/standard/basic_functions_arginfo.h
generated
|
@ -1,5 +1,5 @@
|
|||
/* This is a generated file, edit the .stub.php file instead.
|
||||
* Stub hash: 39d455982dfdea9d0b9b646bc207b05f7108d1b2 */
|
||||
* Stub hash: b0b1fb366a3ba6acfcb460e5b1ac8212c436bf2f */
|
||||
|
||||
ZEND_BEGIN_ARG_WITH_RETURN_TYPE_INFO_EX(arginfo_set_time_limit, 0, 1, _IS_BOOL, 0)
|
||||
ZEND_ARG_TYPE_INFO(0, seconds, IS_LONG, 0)
|
||||
|
@ -2920,11 +2920,11 @@ static const zend_function_entry ext_functions[] = {
|
|||
ZEND_FE(array_reduce, arginfo_array_reduce)
|
||||
ZEND_FE(array_filter, arginfo_array_filter)
|
||||
ZEND_FE(array_map, arginfo_array_map)
|
||||
ZEND_FE(array_key_exists, arginfo_array_key_exists)
|
||||
ZEND_SUPPORTS_COMPILE_TIME_EVAL_FE(array_key_exists, arginfo_array_key_exists)
|
||||
ZEND_FALIAS(key_exists, array_key_exists, arginfo_key_exists)
|
||||
ZEND_FE(array_chunk, arginfo_array_chunk)
|
||||
ZEND_FE(array_combine, arginfo_array_combine)
|
||||
ZEND_FE(array_is_list, arginfo_array_is_list)
|
||||
ZEND_SUPPORTS_COMPILE_TIME_EVAL_FE(array_is_list, arginfo_array_is_list)
|
||||
ZEND_SUPPORTS_COMPILE_TIME_EVAL_FE(base64_encode, arginfo_base64_encode)
|
||||
ZEND_SUPPORTS_COMPILE_TIME_EVAL_FE(base64_decode, arginfo_base64_decode)
|
||||
ZEND_FE(constant, arginfo_constant)
|
||||
|
@ -3090,7 +3090,7 @@ static const zend_function_entry ext_functions[] = {
|
|||
ZEND_FE(dirname, arginfo_dirname)
|
||||
ZEND_FE(pathinfo, arginfo_pathinfo)
|
||||
ZEND_FE(stristr, arginfo_stristr)
|
||||
ZEND_FE(strstr, arginfo_strstr)
|
||||
ZEND_SUPPORTS_COMPILE_TIME_EVAL_FE(strstr, arginfo_strstr)
|
||||
ZEND_FALIAS(strchr, strstr, arginfo_strchr)
|
||||
ZEND_SUPPORTS_COMPILE_TIME_EVAL_FE(strpos, arginfo_strpos)
|
||||
ZEND_SUPPORTS_COMPILE_TIME_EVAL_FE(stripos, arginfo_stripos)
|
||||
|
|
|
@ -527,6 +527,12 @@ static ZEND_FUNCTION(zend_test_zend_call_stack_use_all)
|
|||
}
|
||||
#endif /* ZEND_CHECK_STACK_LIMIT */
|
||||
|
||||
static ZEND_FUNCTION(zend_get_map_ptr_last)
|
||||
{
|
||||
ZEND_PARSE_PARAMETERS_NONE();
|
||||
RETURN_LONG(CG(map_ptr_last));
|
||||
}
|
||||
|
||||
static zend_object *zend_test_class_new(zend_class_entry *class_type)
|
||||
{
|
||||
zend_object *obj = zend_objects_new(class_type);
|
||||
|
|
|
@ -188,6 +188,8 @@ namespace {
|
|||
#endif
|
||||
|
||||
function zend_test_is_string_marked_as_valid_utf8(string $string): bool {}
|
||||
|
||||
function zend_get_map_ptr_last(): int {}
|
||||
}
|
||||
|
||||
namespace ZendTestNS {
|
||||
|
|
10
ext/zend_test/test_arginfo.h
generated
10
ext/zend_test/test_arginfo.h
generated
|
@ -1,5 +1,5 @@
|
|||
/* This is a generated file, edit the .stub.php file instead.
|
||||
* Stub hash: 947056bfe52d586b8a4969e3022f84e83b677e0e */
|
||||
* Stub hash: 904f34b4921ebde937b8f08834750aa78b32b852 */
|
||||
|
||||
ZEND_BEGIN_ARG_WITH_RETURN_TYPE_INFO_EX(arginfo_zend_test_array_return, 0, 0, IS_ARRAY, 0)
|
||||
ZEND_END_ARG_INFO()
|
||||
|
@ -111,6 +111,9 @@ ZEND_BEGIN_ARG_WITH_RETURN_TYPE_INFO_EX(arginfo_zend_test_is_string_marked_as_va
|
|||
ZEND_ARG_TYPE_INFO(0, string, IS_STRING, 0)
|
||||
ZEND_END_ARG_INFO()
|
||||
|
||||
ZEND_BEGIN_ARG_WITH_RETURN_TYPE_INFO_EX(arginfo_zend_get_map_ptr_last, 0, 0, IS_LONG, 0)
|
||||
ZEND_END_ARG_INFO()
|
||||
|
||||
ZEND_BEGIN_ARG_WITH_RETURN_TYPE_INFO_EX(arginfo_ZendTestNS2_namespaced_func, 0, 0, _IS_BOOL, 0)
|
||||
ZEND_END_ARG_INFO()
|
||||
|
||||
|
@ -128,8 +131,7 @@ ZEND_END_ARG_INFO()
|
|||
|
||||
#define arginfo_ZendTestNS2_ZendSubNS_namespaced_deprecated_aliased_func arginfo_zend_test_void_return
|
||||
|
||||
ZEND_BEGIN_ARG_WITH_RETURN_TYPE_INFO_EX(arginfo_class__ZendTestClass_is_object, 0, 0, IS_LONG, 0)
|
||||
ZEND_END_ARG_INFO()
|
||||
#define arginfo_class__ZendTestClass_is_object arginfo_zend_get_map_ptr_last
|
||||
|
||||
#define arginfo_class__ZendTestClass___toString arginfo_zend_get_current_func_name
|
||||
|
||||
|
@ -210,6 +212,7 @@ static ZEND_FUNCTION(zend_test_zend_call_stack_get);
|
|||
static ZEND_FUNCTION(zend_test_zend_call_stack_use_all);
|
||||
#endif
|
||||
static ZEND_FUNCTION(zend_test_is_string_marked_as_valid_utf8);
|
||||
static ZEND_FUNCTION(zend_get_map_ptr_last);
|
||||
static ZEND_FUNCTION(ZendTestNS2_namespaced_func);
|
||||
static ZEND_FUNCTION(ZendTestNS2_namespaced_deprecated_func);
|
||||
static ZEND_FUNCTION(ZendTestNS2_ZendSubNS_namespaced_func);
|
||||
|
@ -268,6 +271,7 @@ static const zend_function_entry ext_functions[] = {
|
|||
ZEND_FE(zend_test_zend_call_stack_use_all, arginfo_zend_test_zend_call_stack_use_all)
|
||||
#endif
|
||||
ZEND_FE(zend_test_is_string_marked_as_valid_utf8, arginfo_zend_test_is_string_marked_as_valid_utf8)
|
||||
ZEND_FE(zend_get_map_ptr_last, arginfo_zend_get_map_ptr_last)
|
||||
ZEND_NS_FALIAS("ZendTestNS2", namespaced_func, ZendTestNS2_namespaced_func, arginfo_ZendTestNS2_namespaced_func)
|
||||
ZEND_NS_DEP_FALIAS("ZendTestNS2", namespaced_deprecated_func, ZendTestNS2_namespaced_deprecated_func, arginfo_ZendTestNS2_namespaced_deprecated_func)
|
||||
ZEND_NS_FALIAS("ZendTestNS2", namespaced_aliased_func, zend_test_void_return, arginfo_ZendTestNS2_namespaced_aliased_func)
|
||||
|
|
52
sapi/fpm/tests/gh8646.phpt
Normal file
52
sapi/fpm/tests/gh8646.phpt
Normal file
|
@ -0,0 +1,52 @@
|
|||
--TEST--
|
||||
GH-8646 (Memory leak PHP FPM 8.1)
|
||||
--EXTENSIONS--
|
||||
zend_test
|
||||
--SKIPIF--
|
||||
<?php include "skipif.inc"; ?>
|
||||
--FILE--
|
||||
<?php
|
||||
|
||||
require_once "tester.inc";
|
||||
|
||||
$cfg = <<<EOT
|
||||
[global]
|
||||
error_log = {{FILE:LOG}}
|
||||
[unconfined]
|
||||
listen = {{ADDR}}
|
||||
pm = dynamic
|
||||
pm.max_children = 5
|
||||
pm.start_servers = 1
|
||||
pm.min_spare_servers = 1
|
||||
pm.max_spare_servers = 3
|
||||
EOT;
|
||||
|
||||
$code = <<<EOT
|
||||
<?php
|
||||
class MyClass {}
|
||||
echo zend_get_map_ptr_last();
|
||||
EOT;
|
||||
|
||||
$tester = new FPM\Tester($cfg, $code);
|
||||
$tester->start();
|
||||
$tester->expectLogStartNotices();
|
||||
$map_ptr_last_values = [];
|
||||
for ($i = 0; $i < 10; $i++) {
|
||||
$map_ptr_last_values[] = (int) $tester->request()->getBody();
|
||||
}
|
||||
// Ensure that map_ptr_last did not increase
|
||||
var_dump(count(array_unique($map_ptr_last_values, SORT_REGULAR)) === 1);
|
||||
$tester->terminate();
|
||||
$tester->expectLogTerminatingNotices();
|
||||
$tester->close();
|
||||
|
||||
?>
|
||||
Done
|
||||
--EXPECT--
|
||||
bool(true)
|
||||
Done
|
||||
--CLEAN--
|
||||
<?php
|
||||
require_once "tester.inc";
|
||||
FPM\Tester::clean();
|
||||
?>
|
Loading…
Add table
Add a link
Reference in a new issue