Download | Plain Text | Line Numbers
diff -Naur a/main/main.c b/main/main.c
--- a/main/main.c 2025-09-19 10:08:21.892371864 +0200
+++ b/main/main.c 2025-09-19 10:08:48.159196785 +0200
@@ -278,6 +278,16 @@
} else {
value = Z_L(1)<<30; /* effectively, no limit */
}
+
+ /* If memory_limit exceeds max_memory_limit, set to max_memory_limit instead. */
+ if (value > PG(max_memory_limit)) {
+ zend_ini_entry *max_mem_limit_ini = zend_hash_str_find_ptr(EG(ini_directives), ZEND_STRL("max_memory_limit"));
+ entry->value = zend_string_init(ZSTR_VAL(max_mem_limit_ini->value), ZSTR_LEN(max_mem_limit_ini->value), true);
+ PG(memory_limit) = PG(max_memory_limit);
+
+ return SUCCESS;
+ }
+
if (zend_set_memory_limit(value) == FAILURE) {
/* When the memory limit is reset to the original level during deactivation, we may be
* using more memory than the original limit while shutdown is still in progress.
@@ -293,6 +303,26 @@
}
/* }}} */
+static PHP_INI_MH(OnChangeMaxMemoryLimit)
+{
+ size_t value;
+ if (new_value) {
+ value = zend_ini_parse_uquantity_warn(new_value, entry->name);
+ } else {
+ value = Z_L(1) << 30; /* effectively, no limit */
+ }
+
+ if (zend_set_memory_limit(value) == FAILURE) {
+ zend_error(E_ERROR, "Failed to set memory limit to %zd bytes (Current memory usage is %zd bytes)", value, zend_memory_usage(true));
+ return FAILURE;
+ }
+
+ PG(max_memory_limit) = value;
+ zend_alter_ini_entry(ZSTR_INIT_LITERAL("memory_limit", 1), new_value, PHP_INI_ALL, stage);
+
+ return SUCCESS;
+}
+
/* {{{ PHP_INI_MH */
static PHP_INI_MH(OnSetLogFilter)
{
@@ -751,7 +781,10 @@
STD_PHP_INI_BOOLEAN("mail.mixed_lf_and_crlf", "0", PHP_INI_SYSTEM|PHP_INI_PERDIR, OnUpdateBool, mail_mixed_lf_and_crlf, php_core_globals, core_globals)
STD_PHP_INI_ENTRY("mail.log", NULL, PHP_INI_SYSTEM|PHP_INI_PERDIR, OnUpdateMailLog, mail_log, php_core_globals, core_globals)
PHP_INI_ENTRY("browscap", NULL, PHP_INI_SYSTEM, OnChangeBrowscap)
- PHP_INI_ENTRY("memory_limit", "128M", PHP_INI_ALL, OnChangeMemoryLimit)
+
+ PHP_INI_ENTRY("max_memory_limit", "-1", PHP_INI_SYSTEM, OnChangeMaxMemoryLimit)
+ PHP_INI_ENTRY("memory_limit", "128M", PHP_INI_ALL, OnChangeMemoryLimit)
+
PHP_INI_ENTRY("precision", "14", PHP_INI_ALL, OnSetPrecision)
PHP_INI_ENTRY("sendmail_from", NULL, PHP_INI_ALL, NULL)
PHP_INI_ENTRY("sendmail_path", DEFAULT_SENDMAIL_PATH, PHP_INI_SYSTEM, NULL)
diff -Naur a/main/php_globals.h b/main/php_globals.h
--- a/main/php_globals.h 2025-09-19 10:08:21.745372843 +0200
+++ b/main/php_globals.h 2025-09-19 10:08:48.159196785 +0200
@@ -72,6 +72,7 @@
zend_long serialize_precision;
zend_long memory_limit;
+ zend_long max_memory_limit;
zend_long max_input_time;
char *error_log;
diff -Naur a/php.ini-development b/php.ini-development
--- a/php.ini-development 2025-09-19 10:08:21.746372837 +0200
+++ b/php.ini-development 2025-09-19 10:08:48.160196778 +0200
@@ -445,6 +445,7 @@
; Maximum amount of memory a script may consume
; https://php.net/memory-limit
memory_limit = 128M
+max_memory_limit = -1
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
; Error handling and logging ;
diff -Naur a/php.ini-production b/php.ini-production
--- a/php.ini-production 2025-09-19 10:08:21.746372837 +0200
+++ b/php.ini-production 2025-09-19 10:08:48.160196778 +0200
@@ -447,6 +447,7 @@
; Maximum amount of memory a script may consume
; https://php.net/memory-limit
memory_limit = 128M
+max_memory_limit = -1
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
; Error handling and logging ;
diff -Naur a/Zend/zend_ini.c b/Zend/zend_ini.c
--- a/Zend/zend_ini.c 2025-08-26 17:05:30.000000000 +0200
+++ b/Zend/zend_ini.c 2025-09-19 10:08:54.379155327 +0200
@@ -247,10 +247,16 @@
zend_unregister_ini_entries_ex(module_number, module_type);
return FAILURE;
}
+
+ zend_string *prev_value = p->value;
+
if (((default_value = zend_get_configuration_directive(p->name)) != NULL) &&
(!p->on_modify || p->on_modify(p, Z_STR_P(default_value), p->mh_arg1, p->mh_arg2, p->mh_arg3, ZEND_INI_STAGE_STARTUP) == SUCCESS)) {
- p->value = zend_new_interned_string(zend_string_copy(Z_STR_P(default_value)));
+ /* Skip assigning the value if the handler has already done so. */
+ if (p->value == prev_value) {
+ p->value = zend_new_interned_string(zend_string_copy(Z_STR_P(default_value)));
+ }
} else {
p->value = ini_entry->value ?
zend_string_init_interned(ini_entry->value, ini_entry->value_length, 1) : NULL;
@@ -388,14 +394,20 @@
zend_hash_add_ptr(EG(modified_ini_directives), ini_entry->name, ini_entry);
}
+ zend_string *prev_value = ini_entry->value;
duplicate = zend_string_copy(new_value);
if (!ini_entry->on_modify
|| ini_entry->on_modify(ini_entry, duplicate, ini_entry->mh_arg1, ini_entry->mh_arg2, ini_entry->mh_arg3, stage) == SUCCESS) {
- if (modified && ini_entry->orig_value != ini_entry->value) { /* we already changed the value, free the changed value */
- zend_string_release(ini_entry->value);
+ if (modified && ini_entry->orig_value != prev_value) { /* we already changed the value, free the changed value */
+ zend_string_release(prev_value);
+ }
+ /* Skip assigning the value if the handler has already done so. */
+ if (ini_entry->value == prev_value) {
+ ini_entry->value = duplicate;
+ } else {
+ zend_string_release(duplicate);
}
- ini_entry->value = duplicate;
} else {
zend_string_release(duplicate);
return FAILURE;