Commit a7204686a9a for php.net
commit a7204686a9a7cb9e1f41a3e307ec092008bf605f
Author: Weilin Du <weilindu@php.net>
Date: Sat Jun 27 23:33:46 2026 +0800
Zend: Revert strict validation of invalid upload_max_filesize and post_max_size values
998bce0 is accidentally pushed directly to master as this should go to a PR branch.
This commit revert that.
diff --git a/NEWS b/NEWS
index 5f1d3b95173..9df461452c1 100644
--- a/NEWS
+++ b/NEWS
@@ -32,8 +32,6 @@ PHP NEWS
surrounding property access). (timwolla)
. Fixed GH-22422 (zend_arena layout mismatch leaked memory in separately
built extensions under AddressSanitizer). (iliaal)
- . Added validation for invalid upload_max_filesize and post_max_size values
- (GH-14695). (Weilin Du)
. TSRM: use local-exec TLS in PIE executables. (henderkes)
. perf: make all static extensions use TSRMG_STATIC. (henderkes)
. Fixed bug GH-22257 (type confusion in Exception::getTraceAsString()).
diff --git a/Zend/tests/zend_ini/gh14695.phpt b/Zend/tests/zend_ini/gh14695.phpt
deleted file mode 100644
index a682c16eff3..00000000000
--- a/Zend/tests/zend_ini/gh14695.phpt
+++ /dev/null
@@ -1,17 +0,0 @@
---TEST--
-GH-14695: Invalid upload_max_filesize and post_max_size values are rejected
---INI--
-upload_max_filesize=1zz
-post_max_size=bogus
---FILE--
-<?php
-
-var_dump(ini_get('upload_max_filesize'));
-var_dump(ini_get('post_max_size'));
-
-?>
---EXPECTF--
-Warning: Invalid "upload_max_filesize" setting. Invalid quantity "1zz": unknown multiplier "z" in %s on line %d
-Warning: Invalid "post_max_size" setting. Invalid quantity "bogus": no valid leading digits in %s on line %d
-string(2) "2M"
-string(2) "8M"
diff --git a/Zend/tests/zend_ini/gh14695_empty.phpt b/Zend/tests/zend_ini/gh14695_empty.phpt
deleted file mode 100644
index 260644122df..00000000000
--- a/Zend/tests/zend_ini/gh14695_empty.phpt
+++ /dev/null
@@ -1,13 +0,0 @@
---TEST--
-GH-14695: Empty upload_max_filesize value is rejected
---INI--
-upload_max_filesize=
---FILE--
-<?php
-
-var_dump(ini_get('upload_max_filesize'));
-
-?>
---EXPECTF--
-Warning: Invalid "upload_max_filesize" setting. Invalid quantity "": no valid leading digits in %s on line %d
-string(2) "2M"
diff --git a/Zend/zend_ini.c b/Zend/zend_ini.c
index 78a1974a92e..093683526d3 100644
--- a/Zend/zend_ini.c
+++ b/Zend/zend_ini.c
@@ -614,12 +614,7 @@ static const char *zend_ini_consume_quantity_prefix(const char *const digits, co
return digits_consumed;
}
-static zend_ulong zend_ini_parse_quantity_internal(
- const zend_string *value,
- zend_ini_parse_quantity_signed_result_t signed_result,
- zend_string **errstr,
- bool strict
-) /* {{{ */
+static zend_ulong zend_ini_parse_quantity_internal(const zend_string *value, zend_ini_parse_quantity_signed_result_t signed_result, zend_string **errstr) /* {{{ */
{
char *digits_end = NULL;
const char *str = ZSTR_VAL(value);
@@ -639,18 +634,6 @@ static zend_ulong zend_ini_parse_quantity_internal(
while (digits < str_end && zend_is_whitespace(*(str_end-1))) {--str_end;}
if (digits == str_end) {
- if (strict) {
- if (ZSTR_LEN(value) == 0) {
- *errstr = zend_strpprintf(0, "Invalid quantity \"\": no valid leading digits");
- } else {
- smart_str_append_escaped(&invalid, ZSTR_VAL(value), ZSTR_LEN(value));
- smart_str_0(&invalid);
- *errstr = zend_strpprintf(0, "Invalid quantity \"%s\": no valid leading digits",
- ZSTR_VAL(invalid.s));
- smart_str_free(&invalid);
- }
- return 0;
- }
*errstr = NULL;
return 0;
}
@@ -670,13 +653,8 @@ static zend_ulong zend_ini_parse_quantity_internal(
smart_str_append_escaped(&invalid, ZSTR_VAL(value), ZSTR_LEN(value));
smart_str_0(&invalid);
- if (strict) {
- *errstr = zend_strpprintf(0, "Invalid quantity \"%s\": no valid leading digits",
- ZSTR_VAL(invalid.s));
- } else {
- *errstr = zend_strpprintf(0, "Invalid quantity \"%s\": no valid leading digits, interpreting as \"0\" for backwards compatibility",
- ZSTR_VAL(invalid.s));
- }
+ *errstr = zend_strpprintf(0, "Invalid quantity \"%s\": no valid leading digits, interpreting as \"0\" for backwards compatibility",
+ ZSTR_VAL(invalid.s));
smart_str_free(&invalid);
return 0;
@@ -712,12 +690,8 @@ static zend_ulong zend_ini_parse_quantity_internal(
base = 2;
break;
default:
- if (strict) {
- *errstr = zend_strpprintf(0, "Invalid prefix \"0%c\"", digits[1]);
- } else {
- *errstr = zend_strpprintf(0, "Invalid prefix \"0%c\", interpreting as \"0\" for backwards compatibility",
- digits[1]);
- }
+ *errstr = zend_strpprintf(0, "Invalid prefix \"0%c\", interpreting as \"0\" for backwards compatibility",
+ digits[1]);
return 0;
}
digits += 2;
@@ -728,13 +702,8 @@ static zend_ulong zend_ini_parse_quantity_internal(
smart_str_append_escaped(&invalid, ZSTR_VAL(value), ZSTR_LEN(value));
smart_str_0(&invalid);
- if (strict) {
- *errstr = zend_strpprintf(0, "Invalid quantity \"%s\": no digits after base prefix",
- ZSTR_VAL(invalid.s));
- } else {
- *errstr = zend_strpprintf(0, "Invalid quantity \"%s\": no digits after base prefix, interpreting as \"0\" for backwards compatibility",
- ZSTR_VAL(invalid.s));
- }
+ *errstr = zend_strpprintf(0, "Invalid quantity \"%s\": no digits after base prefix, interpreting as \"0\" for backwards compatibility",
+ ZSTR_VAL(invalid.s));
smart_str_free(&invalid);
return 0;
@@ -775,13 +744,8 @@ static zend_ulong zend_ini_parse_quantity_internal(
smart_str_append_escaped(&invalid, ZSTR_VAL(value), ZSTR_LEN(value));
smart_str_0(&invalid);
- if (strict) {
- *errstr = zend_strpprintf(0, "Invalid quantity \"%s\": no valid leading digits",
- ZSTR_VAL(invalid.s));
- } else {
- *errstr = zend_strpprintf(0, "Invalid quantity \"%s\": no valid leading digits, interpreting as \"0\" for backwards compatibility",
- ZSTR_VAL(invalid.s));
- }
+ *errstr = zend_strpprintf(0, "Invalid quantity \"%s\": no valid leading digits, interpreting as \"0\" for backwards compatibility",
+ ZSTR_VAL(invalid.s));
smart_str_free(&invalid);
return 0;
@@ -817,13 +781,8 @@ static zend_ulong zend_ini_parse_quantity_internal(
smart_str_append_escaped(&chr, str_end-1, 1);
smart_str_0(&chr);
- if (strict) {
- *errstr = zend_strpprintf(0, "Invalid quantity \"%s\": unknown multiplier \"%s\"",
- ZSTR_VAL(invalid.s), ZSTR_VAL(chr.s));
- } else {
- *errstr = zend_strpprintf(0, "Invalid quantity \"%s\": unknown multiplier \"%s\", interpreting as \"%s\" for backwards compatibility",
- ZSTR_VAL(invalid.s), ZSTR_VAL(chr.s), ZSTR_VAL(interpreted.s));
- }
+ *errstr = zend_strpprintf(0, "Invalid quantity \"%s\": unknown multiplier \"%s\", interpreting as \"%s\" for backwards compatibility",
+ ZSTR_VAL(invalid.s), ZSTR_VAL(chr.s), ZSTR_VAL(interpreted.s));
smart_str_free(&invalid);
smart_str_free(&interpreted);
@@ -856,13 +815,8 @@ static zend_ulong zend_ini_parse_quantity_internal(
smart_str_append_escaped(&chr, str_end-1, 1);
smart_str_0(&chr);
- if (strict) {
- *errstr = zend_strpprintf(0, "Invalid quantity \"%s\": invalid characters before multiplier \"%s\"",
- ZSTR_VAL(invalid.s), ZSTR_VAL(chr.s));
- } else {
- *errstr = zend_strpprintf(0, "Invalid quantity \"%s\", interpreting as \"%s%s\" for backwards compatibility",
- ZSTR_VAL(invalid.s), ZSTR_VAL(interpreted.s), ZSTR_VAL(chr.s));
- }
+ *errstr = zend_strpprintf(0, "Invalid quantity \"%s\", interpreting as \"%s%s\" for backwards compatibility",
+ ZSTR_VAL(invalid.s), ZSTR_VAL(interpreted.s), ZSTR_VAL(chr.s));
smart_str_free(&invalid);
smart_str_free(&interpreted);
@@ -879,13 +833,8 @@ static zend_ulong zend_ini_parse_quantity_internal(
/* Not specifying the resulting value here because the caller may make
* additional conversions. Not specifying the allowed range
* because the caller may do narrower range checks. */
- if (strict) {
- *errstr = zend_strpprintf(0, "Invalid quantity \"%s\": value is out of range",
- ZSTR_VAL(invalid.s));
- } else {
- *errstr = zend_strpprintf(0, "Invalid quantity \"%s\": value is out of range, using overflow result for backwards compatibility",
- ZSTR_VAL(invalid.s));
- }
+ *errstr = zend_strpprintf(0, "Invalid quantity \"%s\": value is out of range, using overflow result for backwards compatibility",
+ ZSTR_VAL(invalid.s));
smart_str_free(&invalid);
smart_str_free(&interpreted);
@@ -901,25 +850,13 @@ static zend_ulong zend_ini_parse_quantity_internal(
ZEND_API zend_long zend_ini_parse_quantity(const zend_string *value, zend_string **errstr) /* {{{ */
{
- return (zend_long) zend_ini_parse_quantity_internal(value, ZEND_INI_PARSE_QUANTITY_SIGNED, errstr, false);
+ return (zend_long) zend_ini_parse_quantity_internal(value, ZEND_INI_PARSE_QUANTITY_SIGNED, errstr);
}
/* }}} */
ZEND_API zend_ulong zend_ini_parse_uquantity(const zend_string *value, zend_string **errstr) /* {{{ */
{
- return zend_ini_parse_quantity_internal(value, ZEND_INI_PARSE_QUANTITY_UNSIGNED, errstr, false);
-}
-/* }}} */
-
-ZEND_API zend_result zend_ini_parse_quantity_strict(const zend_string *value, zend_long *result, zend_string **errstr) /* {{{ */
-{
- zend_long retval = (zend_long) zend_ini_parse_quantity_internal(value, ZEND_INI_PARSE_QUANTITY_SIGNED, errstr, true);
- if (*errstr) {
- return FAILURE;
- }
-
- *result = retval;
- return SUCCESS;
+ return zend_ini_parse_quantity_internal(value, ZEND_INI_PARSE_QUANTITY_UNSIGNED, errstr);
}
/* }}} */
@@ -1037,23 +974,6 @@ ZEND_API ZEND_INI_MH(OnUpdateLong) /* {{{ */
}
/* }}} */
-ZEND_API ZEND_INI_MH(OnUpdateLongStrict) /* {{{ */
-{
- zend_long tmp;
- zend_string *errstr;
- if (UNEXPECTED(zend_ini_parse_quantity_strict(new_value, &tmp, &errstr) == FAILURE)) {
- zend_error(E_WARNING, "Invalid \"%s\" setting. %s", ZSTR_VAL(entry->name), ZSTR_VAL(errstr));
- zend_string_release(errstr);
- return FAILURE;
- }
-
- zend_long *p = ZEND_INI_GET_ADDR();
- *p = tmp;
-
- return SUCCESS;
-}
-/* }}} */
-
ZEND_API ZEND_INI_MH(OnUpdateLongGEZero) /* {{{ */
{
zend_long tmp = zend_ini_parse_quantity_warn(new_value, entry->name);
diff --git a/Zend/zend_ini.h b/Zend/zend_ini.h
index a181048ad9a..dbe650675b6 100644
--- a/Zend/zend_ini.h
+++ b/Zend/zend_ini.h
@@ -142,12 +142,6 @@ ZEND_API zend_long zend_ini_parse_quantity(const zend_string *value, zend_string
*/
ZEND_API zend_ulong zend_ini_parse_uquantity(const zend_string *value, zend_string **errstr);
-/**
- * Strict variant of zend_ini_parse_quantity. Ill-formatted values fail instead
- * of returning a backwards-compatible interpretation.
- */
-ZEND_API zend_result zend_ini_parse_quantity_strict(const zend_string *value, zend_long *result, zend_string **errstr);
-
ZEND_API zend_long zend_ini_parse_quantity_warn(const zend_string *value, zend_string *setting);
ZEND_API zend_ulong zend_ini_parse_uquantity_warn(const zend_string *value, zend_string *setting);
@@ -213,7 +207,6 @@ END_EXTERN_C()
BEGIN_EXTERN_C()
ZEND_API ZEND_INI_MH(OnUpdateBool);
ZEND_API ZEND_INI_MH(OnUpdateLong);
-ZEND_API ZEND_INI_MH(OnUpdateLongStrict);
ZEND_API ZEND_INI_MH(OnUpdateLongGEZero);
ZEND_API ZEND_INI_MH(OnUpdateReal);
/* char* versions */
diff --git a/ext/standard/http.c b/ext/standard/http.c
index 667eddaf0be..d65e7a8acaa 100644
--- a/ext/standard/http.c
+++ b/ext/standard/http.c
@@ -247,17 +247,17 @@ PHP_FUNCTION(http_build_query)
}
/* }}} */
-static zend_result cache_request_parse_body_option(zval *option, const char *option_name, int cache_offset)
+static zend_result cache_request_parse_body_option(HashTable *options, zval *option, int cache_offset)
{
if (option) {
zend_long result;
ZVAL_DEREF(option);
if (Z_TYPE_P(option) == IS_STRING) {
zend_string *errstr;
- if (UNEXPECTED(zend_ini_parse_quantity_strict(Z_STR_P(option), &result, &errstr) == FAILURE)) {
- zend_value_error("Invalid \"%s\" value in $options argument: %s", option_name, ZSTR_VAL(errstr));
+ result = zend_ini_parse_quantity(Z_STR_P(option), &errstr);
+ if (errstr) {
+ zend_error(E_WARNING, "%s", ZSTR_VAL(errstr));
zend_string_release(errstr);
- return FAILURE;
}
} else if (Z_TYPE_P(option) == IS_LONG) {
result = Z_LVAL_P(option);
@@ -290,7 +290,7 @@ static zend_result cache_request_parse_body_options(HashTable *options)
#define CHECK_OPTION(name) \
if (zend_string_equals_literal_ci(key, #name)) { \
- if (cache_request_parse_body_option(value, #name, REQUEST_PARSE_BODY_OPTION_ ## name) == FAILURE) { \
+ if (cache_request_parse_body_option(options, value, REQUEST_PARSE_BODY_OPTION_ ## name) == FAILURE) { \
return FAILURE; \
} \
continue; \
diff --git a/ext/standard/tests/http/request_parse_body/multipart_options_invalid_quantity.phpt b/ext/standard/tests/http/request_parse_body/multipart_options_invalid_quantity.phpt
index 63514f597b5..b1efa0dbc91 100644
--- a/ext/standard/tests/http/request_parse_body/multipart_options_invalid_quantity.phpt
+++ b/ext/standard/tests/http/request_parse_body/multipart_options_invalid_quantity.phpt
@@ -3,17 +3,15 @@
--FILE--
<?php
-foreach (['1GB', ''] as $value) {
- try {
- request_parse_body(options: [
- 'upload_max_filesize' => $value,
- ]);
- } catch (Throwable $e) {
- echo get_class($e), ': ', $e->getMessage(), "\n";
- }
+try {
+ request_parse_body(options: [
+ 'upload_max_filesize' => '1GB',
+ ]);
+} catch (Throwable $e) {
+ echo get_class($e), ': ', $e->getMessage(), "\n";
}
?>
--EXPECTF--
-ValueError: Invalid "upload_max_filesize" value in $options argument: Invalid quantity "1GB": unknown multiplier "B"
-ValueError: Invalid "upload_max_filesize" value in $options argument: Invalid quantity "": no valid leading digits
+Warning: Invalid quantity "1GB": unknown multiplier "B", interpreting as "1" for backwards compatibility in %s on line %d
+RequestParseBodyException: Request does not provide a content type
diff --git a/main/main.c b/main/main.c
index 15bed5be988..6bda55ac874 100644
--- a/main/main.c
+++ b/main/main.c
@@ -845,8 +845,8 @@ PHP_INI_BEGIN()
STD_PHP_INI_ENTRY("open_basedir", NULL, PHP_INI_ALL, OnUpdateBaseDir, open_basedir, php_core_globals, core_globals)
STD_PHP_INI_BOOLEAN("file_uploads", "1", PHP_INI_SYSTEM, OnUpdateBool, file_uploads, php_core_globals, core_globals)
- STD_PHP_INI_ENTRY("upload_max_filesize", "2M", PHP_INI_SYSTEM|PHP_INI_PERDIR, OnUpdateLongStrict, upload_max_filesize, php_core_globals, core_globals)
- STD_PHP_INI_ENTRY("post_max_size", "8M", PHP_INI_SYSTEM|PHP_INI_PERDIR, OnUpdateLongStrict, post_max_size, sapi_globals_struct,sapi_globals)
+ STD_PHP_INI_ENTRY("upload_max_filesize", "2M", PHP_INI_SYSTEM|PHP_INI_PERDIR, OnUpdateLong, upload_max_filesize, php_core_globals, core_globals)
+ STD_PHP_INI_ENTRY("post_max_size", "8M", PHP_INI_SYSTEM|PHP_INI_PERDIR, OnUpdateLong, post_max_size, sapi_globals_struct,sapi_globals)
STD_PHP_INI_ENTRY("upload_tmp_dir", NULL, PHP_INI_SYSTEM, OnUpdateStringUnempty, upload_tmp_dir, php_core_globals, core_globals)
STD_PHP_INI_ENTRY("max_input_nesting_level", "64", PHP_INI_SYSTEM|PHP_INI_PERDIR, OnUpdateLongGEZero, max_input_nesting_level, php_core_globals, core_globals)
STD_PHP_INI_ENTRY("max_input_vars", "1000", PHP_INI_SYSTEM|PHP_INI_PERDIR, OnUpdateLongGEZero, max_input_vars, php_core_globals, core_globals)