Skip to content

Fix GH-17951: Addition of max_memory_limit INI #18011

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 8 commits into
base: master
Choose a base branch
from
54 changes: 52 additions & 2 deletions main/main.c
Original file line number Diff line number Diff line change
Expand Up @@ -320,8 +320,35 @@ static PHP_INI_MH(OnChangeMemoryLimit)
if (new_value) {
value = zend_ini_parse_uquantity_warn(new_value, entry->name);
} else {
value = Z_L(1)<<30; /* effectively, no limit */
value = Z_L(1) << 30; /* effectively, no limit */
}

/* If max_memory_limit is not set to unlimited, verify change */
if (PG(max_memory_limit) != -1) {
if (value == -1) {
zend_error(
stage == ZEND_INI_STAGE_STARTUP ? E_ERROR : E_WARNING,
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Looking at this again, I think it would be better to stick to a warning in all cases. Erroring is very harsh, especially on startup, taking down the entire website.

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'll change all cases to a warning :)

"Failed to set memory_limit to unlimited. memory_limit (currently: " ZEND_LONG_FMT " bytes) cannot be set to unlimited if max_memory_limit (" ZEND_LONG_FMT " bytes) is not unlimited",
PG(memory_limit),
PG(max_memory_limit)
);

return FAILURE;
}

if (value > PG(max_memory_limit)) {
zend_error(
stage == ZEND_INI_STAGE_STARTUP ? E_ERROR : E_WARNING,
"Failed to set memory_limit to %zd bytes. memory_limit (currently: " ZEND_LONG_FMT " bytes) cannot exceed max_memory_limit (" ZEND_LONG_FMT " bytes)",
value,
PG(memory_limit),
PG(max_memory_limit)
);

return FAILURE;
}
}

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.
Expand All @@ -337,6 +364,26 @@ static PHP_INI_MH(OnChangeMemoryLimit)
}
/* }}} */

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(memory_limit) = value;
PG(max_memory_limit) = value;

return SUCCESS;
}

/* {{{ PHP_INI_MH */
static PHP_INI_MH(OnSetLogFilter)
{
Expand Down Expand Up @@ -800,7 +847,10 @@ PHP_INI_BEGIN()
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)
Expand Down
1 change: 1 addition & 0 deletions main/php_globals.h
Original file line number Diff line number Diff line change
Expand Up @@ -72,6 +72,7 @@ struct _php_core_globals {
zend_long serialize_precision;

zend_long memory_limit;
zend_long max_memory_limit;
zend_long max_input_time;

char *error_log;
Expand Down
1 change: 1 addition & 0 deletions php.ini-development
Original file line number Diff line number Diff line change
Expand Up @@ -436,6 +436,7 @@ max_input_time = 60
; Maximum amount of memory a script may consume
; https://php.net/memory-limit
memory_limit = 128M
max_memory_limit = -1

;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
; Error handling and logging ;
Expand Down
1 change: 1 addition & 0 deletions php.ini-production
Original file line number Diff line number Diff line change
Expand Up @@ -438,6 +438,7 @@ max_input_time = 60
; Maximum amount of memory a script may consume
; https://php.net/memory-limit
memory_limit = 128M
max_memory_limit = -1

;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
; Error handling and logging ;
Expand Down
15 changes: 15 additions & 0 deletions tests/basic/gh17951_ini_parse_1.phpt
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
--TEST--
GH-17951 INI Parse 1
--CREDITS--
Frederik Milling Pytlick
frederikpyt@protonmail.com
--INI--
memory_limit=128M
max_memory_limit=-1
--FILE--
<?php
echo ini_get('max_memory_limit') . PHP_EOL;
echo ini_get('memory_limit') . PHP_EOL;
--EXPECT--
-1
128M
15 changes: 15 additions & 0 deletions tests/basic/gh17951_ini_parse_2.phpt
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
--TEST--
GH-17951 INI Parse 2
--CREDITS--
Frederik Milling Pytlick
frederikpyt@protonmail.com
--INI--
memory_limit=-1
max_memory_limit=-1
--FILE--
<?php
echo ini_get('max_memory_limit') . PHP_EOL;
echo ini_get('memory_limit') . PHP_EOL;
--EXPECT--
-1
-1
15 changes: 15 additions & 0 deletions tests/basic/gh17951_ini_parse_3.phpt
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
--TEST--
GH-17951 INI Parse 3
--CREDITS--
Frederik Milling Pytlick
frederikpyt@protonmail.com
--INI--
memory_limit=128M
max_memory_limit=256M
--FILE--
<?php
echo ini_get('max_memory_limit') . PHP_EOL;
echo ini_get('memory_limit') . PHP_EOL;
--EXPECT--
256M
128M
16 changes: 16 additions & 0 deletions tests/basic/gh17951_ini_parse_4.phpt
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
--TEST--
GH-17951 INI Parse 4
--CREDITS--
Frederik Milling Pytlick
frederikpyt@protonmail.com
--INI--
memory_limit=-1
max_memory_limit=128M
--FILE--
<?php
echo ini_get('max_memory_limit') . PHP_EOL;
echo ini_get('memory_limit') . PHP_EOL;
--EXPECTF--
Fatal error: Failed to set memory_limit to unlimited. memory_limit (currently: %d bytes) cannot be set to unlimited if max_memory_limit (%d bytes) is not unlimited in %s
128M
128M
16 changes: 16 additions & 0 deletions tests/basic/gh17951_ini_parse_5.phpt
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
--TEST--
GH-17951 INI Parse 5
--CREDITS--
Frederik Milling Pytlick
frederikpyt@protonmail.com
--INI--
memory_limit=256M
max_memory_limit=128M
--FILE--
<?php
echo ini_get('max_memory_limit') . PHP_EOL;
echo ini_get('memory_limit') . PHP_EOL;
--EXPECTF--
Fatal error: Failed to set memory_limit to %d bytes. memory_limit (currently: %d bytes) cannot exceed max_memory_limit (%d bytes) in %s
128M
128M
14 changes: 14 additions & 0 deletions tests/basic/gh17951_runtime_change_1.phpt
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
--TEST--
GH-17951 Runtime Change 1
--CREDITS--
Frederik Milling Pytlick
frederikpyt@protonmail.com
--INI--
memory_limit=128M
max_memory_limit=512M
--FILE--
<?php
ini_set('memory_limit', '256M');
echo ini_get('memory_limit') . PHP_EOL . PHP_EOL;
--EXPECT--
256M
14 changes: 14 additions & 0 deletions tests/basic/gh17951_runtime_change_2.phpt
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
--TEST--
GH-17951 Runtime Change 2
--CREDITS--
Frederik Milling Pytlick
frederikpyt@protonmail.com
--INI--
memory_limit=128M
max_memory_limit=512M
--FILE--
<?php
ini_set('memory_limit', '512M');
echo ini_get('memory_limit') . PHP_EOL . PHP_EOL;
--EXPECT--
512M
15 changes: 15 additions & 0 deletions tests/basic/gh17951_runtime_change_3.phpt
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
--TEST--
GH-17951 Runtime Change 3
--CREDITS--
Frederik Milling Pytlick
frederikpyt@protonmail.com
--INI--
memory_limit=128M
max_memory_limit=512M
--FILE--
<?php
ini_set('memory_limit', '1024M');
echo ini_get('memory_limit');
--EXPECTF--
Warning: Failed to set memory_limit to %d bytes. memory_limit (currently: %d bytes) cannot exceed max_memory_limit (%d bytes) in %s
128M
15 changes: 15 additions & 0 deletions tests/basic/gh17951_runtime_change_4.phpt
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
--TEST--
GH-17951 Runtime Change 4
--CREDITS--
Frederik Milling Pytlick
frederikpyt@protonmail.com
--INI--
memory_limit=128M
max_memory_limit=512M
--FILE--
<?php
ini_set('memory_limit', '-1');
echo ini_get('memory_limit');
--EXPECTF--
Warning: Failed to set memory_limit to unlimited. memory_limit (currently: %d bytes) cannot be set to unlimited if max_memory_limit (%d bytes) is not unlimited in %s
128M
19 changes: 19 additions & 0 deletions tests/basic/gh17951_runtime_change_5.phpt
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
--TEST--
GH-17951 Runtime Change 5
--CREDITS--
Frederik Milling Pytlick
frederikpyt@protonmail.com
--INI--
memory_limit=128M
max_memory_limit=512M
--FILE--
<?php
var_dump(ini_set('max_memory_limit', '128M'));
var_dump(ini_set('max_memory_limit', '256M'));
var_dump(ini_set('max_memory_limit', '512M'));
var_dump(ini_set('max_memory_limit', '-1'));
--EXPECT--
bool(false)
bool(false)
bool(false)
bool(false)
Loading