From 9341c6e5b19c7f6e3a4f32b6de5981d31af77852 Mon Sep 17 00:00:00 2001 From: Frederik Milling Pytlick Date: Mon, 10 Mar 2025 11:15:52 +0100 Subject: [PATCH 1/8] Fix GH-17951: Addition of max_memory_limit INI --- main/main.c | 79 ++++++++++++++++++----- main/php_globals.h | 1 + php.ini-development | 1 + php.ini-production | 1 + tests/basic/gh17951_ini_parse_1.phpt | 13 ++++ tests/basic/gh17951_ini_parse_2.phpt | 13 ++++ tests/basic/gh17951_ini_parse_3.phpt | 13 ++++ tests/basic/gh17951_ini_parse_4.phpt | 12 ++++ tests/basic/gh17951_ini_parse_5.phpt | 12 ++++ tests/basic/gh17951_runtime_change_1.phpt | 14 ++++ tests/basic/gh17951_runtime_change_2.phpt | 14 ++++ tests/basic/gh17951_runtime_change_3.phpt | 15 +++++ tests/basic/gh17951_runtime_change_4.phpt | 15 +++++ tests/basic/gh17951_runtime_change_5.phpt | 19 ++++++ 14 files changed, 206 insertions(+), 16 deletions(-) create mode 100644 tests/basic/gh17951_ini_parse_1.phpt create mode 100644 tests/basic/gh17951_ini_parse_2.phpt create mode 100644 tests/basic/gh17951_ini_parse_3.phpt create mode 100644 tests/basic/gh17951_ini_parse_4.phpt create mode 100644 tests/basic/gh17951_ini_parse_5.phpt create mode 100644 tests/basic/gh17951_runtime_change_1.phpt create mode 100644 tests/basic/gh17951_runtime_change_2.phpt create mode 100644 tests/basic/gh17951_runtime_change_3.phpt create mode 100644 tests/basic/gh17951_runtime_change_4.phpt create mode 100644 tests/basic/gh17951_runtime_change_5.phpt diff --git a/main/main.c b/main/main.c index 4075be8b377e3..963d5452d70bf 100644 --- a/main/main.c +++ b/main/main.c @@ -317,23 +317,67 @@ static PHP_INI_MH(OnSetSerializePrecision) static PHP_INI_MH(OnChangeMemoryLimit) { 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) { - /* 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. - * Ignore a failure for now, and set the memory limit when the memory manager has been - * shut down and the minimal amount of memory is used. */ - if (stage != ZEND_INI_STAGE_DEACTIVATE) { - zend_error(E_WARNING, "Failed to set memory limit to %zd bytes (Current memory usage is %zd bytes)", value, zend_memory_usage(true)); - return FAILURE; + + if (new_value) { + value = zend_ini_parse_uquantity_warn(new_value, entry->name); + } else { + value = Z_L(1) << 30; /* effectively, no limit */ + } + + /* If max_memory_limit is not set to unlimited, memory_limit cannot be set to unlimited. */ + if (value == -1 && PG(max_memory_limit) != -1) { + if (PG(memory_limit) == 0) { + /* memory_limit exceeds max_memory_limit at INI parsing. */ + zend_error(E_ERROR, "memory_limit cannot be set to unlimited when max_memory_limit (%zd bytes) is not unlimited", PG(max_memory_limit)); + zend_bailout(); + exit(1); + } else { + /* new memory_limit exceeds max_memory_limit at runtime. */ + zend_error(E_WARNING, "Failed to set memory_limit to unlimited. memory_limit (currently: %zd bytes) cannot be set to unlimited if max_memory_limit (%zd bytes) is not unlimited", PG(memory_limit), PG(max_memory_limit)); } + + return FAILURE; } - PG(memory_limit) = value; - return SUCCESS; + + /* Enforce max_memory_limit if not unlimited */ + if (PG(max_memory_limit) != -1 && value > PG(max_memory_limit)) { + if (PG(memory_limit) == 0) { + /* memory_limit exceeds max_memory_limit at INI parsing. */ + zend_error(E_ERROR, "memory_limit (%zd bytes) exceeds max_memory_limit (%zd bytes)", value, PG(max_memory_limit)); + zend_bailout(); + exit(1); + } else { + /* new memory_limit exceeds max_memory_limit at runtime. */ + zend_error(E_WARNING, "Failed to set memory_limit to %zd bytes. memory_limit (currently: %zd bytes) cannot exceed max_memory_limit (%zd bytes)", value, PG(memory_limit), PG(max_memory_limit)); + } + + return FAILURE; + } + + if (zend_set_memory_limit(value) == FAILURE) { + if (stage != ZEND_INI_STAGE_DEACTIVATE) { + zend_error(E_WARNING, "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; + return SUCCESS; +} +/* }}} */ + +/* {{{ PHP_INI_MH */ +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 */ + } + + PG(max_memory_limit) = value; + return SUCCESS; } /* }}} */ @@ -800,7 +844,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) diff --git a/main/php_globals.h b/main/php_globals.h index b2f2696c2db2c..e7a127528ff2d 100644 --- a/main/php_globals.h +++ b/main/php_globals.h @@ -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; diff --git a/php.ini-development b/php.ini-development index 37619fd071c55..80ac80557f1b2 100644 --- a/php.ini-development +++ b/php.ini-development @@ -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 ; diff --git a/php.ini-production b/php.ini-production index 60069f69b8b90..a5b70aed6c976 100644 --- a/php.ini-production +++ b/php.ini-production @@ -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 ; diff --git a/tests/basic/gh17951_ini_parse_1.phpt b/tests/basic/gh17951_ini_parse_1.phpt new file mode 100644 index 0000000000000..0596d30c88ff5 --- /dev/null +++ b/tests/basic/gh17951_ini_parse_1.phpt @@ -0,0 +1,13 @@ +--TEST-- +GH-17951 INI Parse 1 +--CREDITS-- +Frederik Milling Pytlick +frederikpyt@protonmail.com +--INI-- +memory_limit=128M +max_memory_limit=-1 +--FILE-- + Date: Mon, 10 Mar 2025 12:36:04 +0100 Subject: [PATCH 2/8] Fix format specifiers to match type & utilize stage --- main/main.c | 16 ++++++---------- 1 file changed, 6 insertions(+), 10 deletions(-) diff --git a/main/main.c b/main/main.c index 963d5452d70bf..aae8f6142c39a 100644 --- a/main/main.c +++ b/main/main.c @@ -326,14 +326,12 @@ static PHP_INI_MH(OnChangeMemoryLimit) /* If max_memory_limit is not set to unlimited, memory_limit cannot be set to unlimited. */ if (value == -1 && PG(max_memory_limit) != -1) { - if (PG(memory_limit) == 0) { + if (stage == ZEND_INI_STAGE_STARTUP) { /* memory_limit exceeds max_memory_limit at INI parsing. */ - zend_error(E_ERROR, "memory_limit cannot be set to unlimited when max_memory_limit (%zd bytes) is not unlimited", PG(max_memory_limit)); - zend_bailout(); - exit(1); + zend_error_noreturn(E_ERROR, "memory_limit cannot be set to unlimited when max_memory_limit (%lld bytes) is not unlimited", PG(max_memory_limit)); } else { /* new memory_limit exceeds max_memory_limit at runtime. */ - zend_error(E_WARNING, "Failed to set memory_limit to unlimited. memory_limit (currently: %zd bytes) cannot be set to unlimited if max_memory_limit (%zd bytes) is not unlimited", PG(memory_limit), PG(max_memory_limit)); + zend_error(E_WARNING, "Failed to set memory_limit to unlimited. memory_limit (currently: %lld bytes) cannot be set to unlimited if max_memory_limit (%lld bytes) is not unlimited", PG(memory_limit), PG(max_memory_limit)); } return FAILURE; @@ -341,14 +339,12 @@ static PHP_INI_MH(OnChangeMemoryLimit) /* Enforce max_memory_limit if not unlimited */ if (PG(max_memory_limit) != -1 && value > PG(max_memory_limit)) { - if (PG(memory_limit) == 0) { + if (stage == ZEND_INI_STAGE_STARTUP) { /* memory_limit exceeds max_memory_limit at INI parsing. */ - zend_error(E_ERROR, "memory_limit (%zd bytes) exceeds max_memory_limit (%zd bytes)", value, PG(max_memory_limit)); - zend_bailout(); - exit(1); + zend_error_noreturn(E_ERROR, "memory_limit (%zd bytes) exceeds max_memory_limit (%lld bytes)", value, PG(max_memory_limit)); } else { /* new memory_limit exceeds max_memory_limit at runtime. */ - zend_error(E_WARNING, "Failed to set memory_limit to %zd bytes. memory_limit (currently: %zd bytes) cannot exceed max_memory_limit (%zd bytes)", value, PG(memory_limit), PG(max_memory_limit)); + zend_error(E_WARNING, "Failed to set memory_limit to %zd bytes. memory_limit (currently: %lld bytes) cannot exceed max_memory_limit (%lld bytes)", value, PG(memory_limit), PG(max_memory_limit)); } return FAILURE; From 2d61446fe0001805435e8d6a53b602e0aa031a4a Mon Sep 17 00:00:00 2001 From: Frederik Milling Pytlick Date: Mon, 10 Mar 2025 13:09:37 +0100 Subject: [PATCH 3/8] Fix format specifiers to be platform specific --- main/main.c | 30 ++++++++++++++++++++++++++---- 1 file changed, 26 insertions(+), 4 deletions(-) diff --git a/main/main.c b/main/main.c index aae8f6142c39a..1303e5fb9808c 100644 --- a/main/main.c +++ b/main/main.c @@ -328,10 +328,20 @@ static PHP_INI_MH(OnChangeMemoryLimit) if (value == -1 && PG(max_memory_limit) != -1) { if (stage == ZEND_INI_STAGE_STARTUP) { /* memory_limit exceeds max_memory_limit at INI parsing. */ - zend_error_noreturn(E_ERROR, "memory_limit cannot be set to unlimited when max_memory_limit (%lld bytes) is not unlimited", PG(max_memory_limit)); + zend_error( + E_ERROR, + "memory_limit cannot be set to unlimited when max_memory_limit (" ZEND_LONG_FMT " bytes) is not unlimited", + PG(max_memory_limit) + ); + exit(1); } else { /* new memory_limit exceeds max_memory_limit at runtime. */ - zend_error(E_WARNING, "Failed to set memory_limit to unlimited. memory_limit (currently: %lld bytes) cannot be set to unlimited if max_memory_limit (%lld bytes) is not unlimited", PG(memory_limit), PG(max_memory_limit)); + zend_error( + E_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; @@ -341,10 +351,22 @@ static PHP_INI_MH(OnChangeMemoryLimit) if (PG(max_memory_limit) != -1 && value > PG(max_memory_limit)) { if (stage == ZEND_INI_STAGE_STARTUP) { /* memory_limit exceeds max_memory_limit at INI parsing. */ - zend_error_noreturn(E_ERROR, "memory_limit (%zd bytes) exceeds max_memory_limit (%lld bytes)", value, PG(max_memory_limit)); + zend_error( + E_ERROR, + "memory_limit (%zd bytes) exceeds max_memory_limit (" ZEND_LONG_FMT " bytes)", + value, + PG(max_memory_limit) + ); + exit(1); } else { /* new memory_limit exceeds max_memory_limit at runtime. */ - zend_error(E_WARNING, "Failed to set memory_limit to %zd bytes. memory_limit (currently: %lld bytes) cannot exceed max_memory_limit (%lld bytes)", value, PG(memory_limit), PG(max_memory_limit)); + zend_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; From 9e42b57c661d48ff4019910f84be3896ce71c5e4 Mon Sep 17 00:00:00 2001 From: Frederik Milling Pytlick Date: Mon, 10 Mar 2025 14:57:12 +0100 Subject: [PATCH 4/8] Fix scenario where max_memory_limit could be lower than memory_limit --- main/main.c | 64 ++++++++++++++-------------- tests/basic/gh17951_ini_parse_4.phpt | 6 ++- tests/basic/gh17951_ini_parse_5.phpt | 4 ++ 3 files changed, 41 insertions(+), 33 deletions(-) diff --git a/main/main.c b/main/main.c index 1303e5fb9808c..c55c4576b983a 100644 --- a/main/main.c +++ b/main/main.c @@ -324,42 +324,20 @@ static PHP_INI_MH(OnChangeMemoryLimit) value = Z_L(1) << 30; /* effectively, no limit */ } - /* If max_memory_limit is not set to unlimited, memory_limit cannot be set to unlimited. */ - if (value == -1 && PG(max_memory_limit) != -1) { - if (stage == ZEND_INI_STAGE_STARTUP) { - /* memory_limit exceeds max_memory_limit at INI parsing. */ - zend_error( - E_ERROR, - "memory_limit cannot be set to unlimited when max_memory_limit (" ZEND_LONG_FMT " bytes) is not unlimited", - PG(max_memory_limit) - ); - exit(1); - } else { - /* new memory_limit exceeds max_memory_limit at runtime. */ + /* If max_memory_limit is not set to unlimited, verify change */ + if (PG(max_memory_limit) != 0 && PG(max_memory_limit) != -1) { + if (value == -1) { zend_error( E_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; - } + return FAILURE; + } - /* Enforce max_memory_limit if not unlimited */ - if (PG(max_memory_limit) != -1 && value > PG(max_memory_limit)) { - if (stage == ZEND_INI_STAGE_STARTUP) { - /* memory_limit exceeds max_memory_limit at INI parsing. */ - zend_error( - E_ERROR, - "memory_limit (%zd bytes) exceeds max_memory_limit (" ZEND_LONG_FMT " bytes)", - value, - PG(max_memory_limit) - ); - exit(1); - } else { - /* new memory_limit exceeds max_memory_limit at runtime. */ + if (value > PG(max_memory_limit)) { zend_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)", @@ -367,10 +345,10 @@ static PHP_INI_MH(OnChangeMemoryLimit) PG(memory_limit), PG(max_memory_limit) ); - } - return FAILURE; - } + return FAILURE; + } + } if (zend_set_memory_limit(value) == FAILURE) { if (stage != ZEND_INI_STAGE_DEACTIVATE) { @@ -394,6 +372,28 @@ static PHP_INI_MH(OnChangeMaxMemoryLimit) value = Z_L(1) << 30; /* effectively, no limit */ } + /* If new value is not unlimited, verify change */ + if (value != -1) { + if (PG(memory_limit) == -1) { + zend_error( + E_ERROR, + "memory_limit is set to unlimited, you cannot set max_memory_limit to %zd bytes", + value + ); + return FAILURE; + } + + if (PG(memory_limit) > value) { + zend_error( + E_ERROR, + "memory_limit (" ZEND_LONG_FMT " bytes) exceeds max_memory_limit (%zd bytes)", + PG(memory_limit), + value + ); + return FAILURE; + } + } + PG(max_memory_limit) = value; return SUCCESS; } @@ -863,8 +863,8 @@ PHP_INI_BEGIN() 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("max_memory_limit", "-1", PHP_INI_SYSTEM, OnChangeMaxMemoryLimit) PHP_INI_ENTRY("memory_limit", "128M", PHP_INI_ALL, OnChangeMemoryLimit) + PHP_INI_ENTRY("max_memory_limit", "-1", PHP_INI_SYSTEM, OnChangeMaxMemoryLimit) PHP_INI_ENTRY("precision", "14", PHP_INI_ALL, OnSetPrecision) PHP_INI_ENTRY("sendmail_from", NULL, PHP_INI_ALL, NULL) diff --git a/tests/basic/gh17951_ini_parse_4.phpt b/tests/basic/gh17951_ini_parse_4.phpt index df46360a24067..ddbb19ebbd597 100644 --- a/tests/basic/gh17951_ini_parse_4.phpt +++ b/tests/basic/gh17951_ini_parse_4.phpt @@ -8,5 +8,9 @@ memory_limit=-1 max_memory_limit=128M --FILE-- Date: Mon, 10 Mar 2025 15:58:27 +0100 Subject: [PATCH 5/8] Fix issues addressed during review --- main/main.c | 44 ++++++++++++++++++++++++-------------------- main/php_globals.h | 2 +- 2 files changed, 25 insertions(+), 21 deletions(-) diff --git a/main/main.c b/main/main.c index c55c4576b983a..5b4c5c0ba9e41 100644 --- a/main/main.c +++ b/main/main.c @@ -318,11 +318,11 @@ static PHP_INI_MH(OnChangeMemoryLimit) { 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 (new_value) { + value = zend_ini_parse_uquantity_warn(new_value, entry->name); + } else { + value = Z_L(1) << 30; /* effectively, no limit */ + } /* If max_memory_limit is not set to unlimited, verify change */ if (PG(max_memory_limit) != 0 && PG(max_memory_limit) != -1) { @@ -350,15 +350,19 @@ static PHP_INI_MH(OnChangeMemoryLimit) } } - if (zend_set_memory_limit(value) == FAILURE) { - if (stage != ZEND_INI_STAGE_DEACTIVATE) { - zend_error(E_WARNING, "Failed to set memory limit to %zd bytes (Current memory usage is %zd bytes)", value, zend_memory_usage(true)); - 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. + * Ignore a failure for now, and set the memory limit when the memory manager has been + * shut down and the minimal amount of memory is used. */ + if (stage != ZEND_INI_STAGE_DEACTIVATE) { + zend_error(E_WARNING, "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; - return SUCCESS; + PG(memory_limit) = value; + return SUCCESS; } /* }}} */ @@ -366,11 +370,11 @@ 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 (new_value) { + value = zend_ini_parse_uquantity_warn(new_value, entry->name); + } else { + value = Z_L(1) << 30; /* effectively, no limit */ + } /* If new value is not unlimited, verify change */ if (value != -1) { @@ -394,8 +398,8 @@ static PHP_INI_MH(OnChangeMaxMemoryLimit) } } - PG(max_memory_limit) = value; - return SUCCESS; + PG(max_memory_limit) = value; + return SUCCESS; } /* }}} */ diff --git a/main/php_globals.h b/main/php_globals.h index e7a127528ff2d..59ad55ffff4c8 100644 --- a/main/php_globals.h +++ b/main/php_globals.h @@ -72,7 +72,7 @@ struct _php_core_globals { zend_long serialize_precision; zend_long memory_limit; - zend_long max_memory_limit; + zend_long max_memory_limit; zend_long max_input_time; char *error_log; From 72f4df495a978191d166d3e820fa5b3ff1ccd135 Mon Sep 17 00:00:00 2001 From: Frederik Milling Pytlick Date: Tue, 11 Mar 2025 09:26:48 +0100 Subject: [PATCH 6/8] Made it so max_memory_limit INI is set before memory_limit INI --- main/main.c | 33 ++++++++-------------------- tests/basic/gh17951_ini_parse_1.phpt | 6 +++-- tests/basic/gh17951_ini_parse_2.phpt | 6 +++-- tests/basic/gh17951_ini_parse_3.phpt | 6 +++-- tests/basic/gh17951_ini_parse_4.phpt | 6 ++--- tests/basic/gh17951_ini_parse_5.phpt | 6 ++--- 6 files changed, 27 insertions(+), 36 deletions(-) diff --git a/main/main.c b/main/main.c index 5b4c5c0ba9e41..a585b664eb171 100644 --- a/main/main.c +++ b/main/main.c @@ -325,10 +325,10 @@ static PHP_INI_MH(OnChangeMemoryLimit) } /* If max_memory_limit is not set to unlimited, verify change */ - if (PG(max_memory_limit) != 0 && PG(max_memory_limit) != -1) { + if (PG(max_memory_limit) != -1) { if (value == -1) { zend_error( - E_WARNING, + stage == ZEND_INI_STAGE_STARTUP ? E_ERROR : E_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) @@ -339,7 +339,7 @@ static PHP_INI_MH(OnChangeMemoryLimit) if (value > PG(max_memory_limit)) { zend_error( - E_WARNING, + 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), @@ -376,29 +376,14 @@ static PHP_INI_MH(OnChangeMaxMemoryLimit) value = Z_L(1) << 30; /* effectively, no limit */ } - /* If new value is not unlimited, verify change */ - if (value != -1) { - if (PG(memory_limit) == -1) { - zend_error( - E_ERROR, - "memory_limit is set to unlimited, you cannot set max_memory_limit to %zd bytes", - value - ); - return FAILURE; - } - - if (PG(memory_limit) > value) { - zend_error( - E_ERROR, - "memory_limit (" ZEND_LONG_FMT " bytes) exceeds max_memory_limit (%zd bytes)", - PG(memory_limit), - value - ); - return FAILURE; - } + 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; } /* }}} */ @@ -867,8 +852,8 @@ PHP_INI_BEGIN() 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) diff --git a/tests/basic/gh17951_ini_parse_1.phpt b/tests/basic/gh17951_ini_parse_1.phpt index 0596d30c88ff5..621c4984648f3 100644 --- a/tests/basic/gh17951_ini_parse_1.phpt +++ b/tests/basic/gh17951_ini_parse_1.phpt @@ -8,6 +8,8 @@ memory_limit=128M max_memory_limit=-1 --FILE-- Date: Tue, 11 Mar 2025 12:09:40 +0100 Subject: [PATCH 7/8] Fix whitespace and remove vim comments --- main/main.c | 4 ---- 1 file changed, 4 deletions(-) diff --git a/main/main.c b/main/main.c index a585b664eb171..725c6c9c9c5c6 100644 --- a/main/main.c +++ b/main/main.c @@ -317,7 +317,6 @@ static PHP_INI_MH(OnSetSerializePrecision) static PHP_INI_MH(OnChangeMemoryLimit) { size_t value; - if (new_value) { value = zend_ini_parse_uquantity_warn(new_value, entry->name); } else { @@ -360,13 +359,11 @@ static PHP_INI_MH(OnChangeMemoryLimit) return FAILURE; } } - PG(memory_limit) = value; return SUCCESS; } /* }}} */ -/* {{{ PHP_INI_MH */ static PHP_INI_MH(OnChangeMaxMemoryLimit) { size_t value; @@ -386,7 +383,6 @@ static PHP_INI_MH(OnChangeMaxMemoryLimit) return SUCCESS; } -/* }}} */ /* {{{ PHP_INI_MH */ static PHP_INI_MH(OnSetLogFilter) From 1d49976296d96d2002437b751a5f453f785905ce Mon Sep 17 00:00:00 2001 From: Frederik Pytlick Date: Tue, 22 Apr 2025 09:30:33 +0200 Subject: [PATCH 8/8] Changed fatals to warnings during startup --- main/main.c | 4 ++-- tests/basic/gh17951_ini_parse_4.phpt | 2 +- tests/basic/gh17951_ini_parse_5.phpt | 2 +- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/main/main.c b/main/main.c index 725c6c9c9c5c6..ecc67074cc4c8 100644 --- a/main/main.c +++ b/main/main.c @@ -327,7 +327,7 @@ static PHP_INI_MH(OnChangeMemoryLimit) if (PG(max_memory_limit) != -1) { if (value == -1) { zend_error( - stage == ZEND_INI_STAGE_STARTUP ? E_ERROR : E_WARNING, + E_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) @@ -338,7 +338,7 @@ static PHP_INI_MH(OnChangeMemoryLimit) if (value > PG(max_memory_limit)) { zend_error( - stage == ZEND_INI_STAGE_STARTUP ? E_ERROR : E_WARNING, + 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), diff --git a/tests/basic/gh17951_ini_parse_4.phpt b/tests/basic/gh17951_ini_parse_4.phpt index 17f81f644067e..9f7aa7df3aef5 100644 --- a/tests/basic/gh17951_ini_parse_4.phpt +++ b/tests/basic/gh17951_ini_parse_4.phpt @@ -11,6 +11,6 @@ max_memory_limit=128M 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 +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 128M diff --git a/tests/basic/gh17951_ini_parse_5.phpt b/tests/basic/gh17951_ini_parse_5.phpt index 0cbdc8bcc6f95..d0d243b890349 100644 --- a/tests/basic/gh17951_ini_parse_5.phpt +++ b/tests/basic/gh17951_ini_parse_5.phpt @@ -11,6 +11,6 @@ max_memory_limit=128M 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 +Warning: Failed to set memory_limit to %d bytes. memory_limit (currently: %d bytes) cannot exceed max_memory_limit (%d bytes) in %s 128M 128M