From 070e24d7a91a49fce56b5ee4d5a102d022d3e724 Mon Sep 17 00:00:00 2001 From: Nikita Popov Date: Thu, 11 Feb 2021 10:42:55 +0100 Subject: [PATCH] Allow all scalar types in ini_set() This changes ini_set() to accept all scalar types (string|int|float|bool|null) for the new value. The idea here is that while the INI system ultimately works with strings, its value interpretation is designed to be consistent with PHP's casting rules, e.g. "1" and "" are interpreted as boolean true and false respectively. I personally believe that writing ini_set('precision', 10) makes more sense than ini_set('precision', '10'), and find strict_types to be unnecessarily pedantic here. Closes GH-6680. --- ext/standard/basic_functions.c | 20 ++++++++--- ext/standard/basic_functions.stub.php | 2 +- ext/standard/basic_functions_arginfo.h | 9 +++-- .../general_functions/ini_set_types.phpt | 34 +++++++++++++++++++ 4 files changed, 56 insertions(+), 9 deletions(-) create mode 100644 ext/standard/tests/general_functions/ini_set_types.phpt diff --git a/ext/standard/basic_functions.c b/ext/standard/basic_functions.c index 54c3188771..4084f5d853 100755 --- a/ext/standard/basic_functions.c +++ b/ext/standard/basic_functions.c @@ -2086,14 +2086,19 @@ static int php_ini_check_path(char *option_name, size_t option_len, char *new_op PHP_FUNCTION(ini_set) { zend_string *varname; - zend_string *new_value; + zval *new_value; zend_string *val; ZEND_PARSE_PARAMETERS_START(2, 2) Z_PARAM_STR(varname) - Z_PARAM_STR(new_value) + Z_PARAM_ZVAL(new_value) ZEND_PARSE_PARAMETERS_END(); + if (Z_TYPE_P(new_value) > IS_STRING) { + zend_argument_type_error(2, "must be of type string|int|float|bool|null"); + RETURN_THROWS(); + } + val = zend_ini_get_value(varname); if (val) { @@ -2102,6 +2107,9 @@ PHP_FUNCTION(ini_set) RETVAL_FALSE; } + zend_string *new_value_tmp_str; + zend_string *new_value_str = zval_get_tmp_string(new_value, &new_value_tmp_str); + #define _CHECK_PATH(var, var_len, ini) php_ini_check_path(var, var_len, ini, sizeof(ini)) /* open basedir check */ if (PG(open_basedir)) { @@ -2111,18 +2119,20 @@ PHP_FUNCTION(ini_set) _CHECK_PATH(ZSTR_VAL(varname), ZSTR_LEN(varname), "mail.log") || _CHECK_PATH(ZSTR_VAL(varname), ZSTR_LEN(varname), "java.library.path") || _CHECK_PATH(ZSTR_VAL(varname), ZSTR_LEN(varname), "vpopmail.directory")) { - if (php_check_open_basedir(ZSTR_VAL(new_value))) { + if (php_check_open_basedir(ZSTR_VAL(new_value_str))) { zval_ptr_dtor_str(return_value); + zend_tmp_string_release(new_value_tmp_str); RETURN_FALSE; } } } #undef _CHECK_PATH - if (zend_alter_ini_entry_ex(varname, new_value, PHP_INI_USER, PHP_INI_STAGE_RUNTIME, 0) == FAILURE) { + if (zend_alter_ini_entry_ex(varname, new_value_str, PHP_INI_USER, PHP_INI_STAGE_RUNTIME, 0) == FAILURE) { zval_ptr_dtor_str(return_value); - RETURN_FALSE; + RETVAL_FALSE; } + zend_tmp_string_release(new_value_tmp_str); } /* }}} */ diff --git a/ext/standard/basic_functions.stub.php b/ext/standard/basic_functions.stub.php index 197af9e3e1..3a7e0de174 100755 --- a/ext/standard/basic_functions.stub.php +++ b/ext/standard/basic_functions.stub.php @@ -318,7 +318,7 @@ function ini_get(string $option): string|false {} function ini_get_all(?string $extension = null, bool $details = true): array|false {} -function ini_set(string $option, string $value): string|false {} +function ini_set(string $option, string|int|float|bool|null $value): string|false {} /** @alias ini_set */ function ini_alter(string $option, string $value): string|false {} diff --git a/ext/standard/basic_functions_arginfo.h b/ext/standard/basic_functions_arginfo.h index 514a0338d5..1c7f6b00ec 100644 --- a/ext/standard/basic_functions_arginfo.h +++ b/ext/standard/basic_functions_arginfo.h @@ -1,5 +1,5 @@ /* This is a generated file, edit the .stub.php file instead. - * Stub hash: 4f4ed195a688735d48aeb3b7cd390d8463a07c26 */ + * Stub hash: e9f39cbc595f0f2cdd84e58d4857f9fdb03ff7b7 */ 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) @@ -491,10 +491,13 @@ ZEND_END_ARG_INFO() ZEND_BEGIN_ARG_WITH_RETURN_TYPE_MASK_EX(arginfo_ini_set, 0, 2, MAY_BE_STRING|MAY_BE_FALSE) ZEND_ARG_TYPE_INFO(0, option, IS_STRING, 0) - ZEND_ARG_TYPE_INFO(0, value, IS_STRING, 0) + ZEND_ARG_TYPE_MASK(0, value, MAY_BE_STRING|MAY_BE_LONG|MAY_BE_DOUBLE|MAY_BE_BOOL|MAY_BE_NULL, NULL) ZEND_END_ARG_INFO() -#define arginfo_ini_alter arginfo_ini_set +ZEND_BEGIN_ARG_WITH_RETURN_TYPE_MASK_EX(arginfo_ini_alter, 0, 2, MAY_BE_STRING|MAY_BE_FALSE) + ZEND_ARG_TYPE_INFO(0, option, IS_STRING, 0) + ZEND_ARG_TYPE_INFO(0, value, IS_STRING, 0) +ZEND_END_ARG_INFO() ZEND_BEGIN_ARG_WITH_RETURN_TYPE_INFO_EX(arginfo_ini_restore, 0, 1, IS_VOID, 0) ZEND_ARG_TYPE_INFO(0, option, IS_STRING, 0) diff --git a/ext/standard/tests/general_functions/ini_set_types.phpt b/ext/standard/tests/general_functions/ini_set_types.phpt new file mode 100644 index 0000000000..16def381db --- /dev/null +++ b/ext/standard/tests/general_functions/ini_set_types.phpt @@ -0,0 +1,34 @@ +--TEST-- +ini_set() accepts non-strings under strict_types +--FILE-- +getMessage(), "\n"; +} + +?> +--EXPECT-- +string(0) "" +string(1) "1" +string(0) "" +string(1) "6" +string(4) "3.14" +ini_set(): Argument #2 ($value) must be of type string|int|float|bool|null -- 2.50.1