diff options
29 files changed, 467 insertions, 283 deletions
diff --git a/Zend/zend_API.c b/Zend/zend_API.c index 14abdd1a38..ee0e361ed9 100644 --- a/Zend/zend_API.c +++ b/Zend/zend_API.c @@ -221,15 +221,21 @@ ZEND_API ZEND_COLD void ZEND_FASTCALL zend_wrong_parameter_error(int error_code, case ZPP_ERROR_WRONG_CLASS_OR_NULL: zend_wrong_parameter_class_or_null_error(num, name, arg); break; - case ZPP_ERROR_WRONG_ARG: - zend_wrong_parameter_type_error(num, expected_type, arg); - break; case ZPP_ERROR_WRONG_CLASS_OR_STRING: zend_wrong_parameter_class_or_string_error(num, name, arg); break; case ZPP_ERROR_WRONG_CLASS_OR_STRING_OR_NULL: zend_wrong_parameter_class_or_string_or_null_error(num, name, arg); break; + case ZPP_ERROR_WRONG_CLASS_OR_LONG: + zend_wrong_parameter_class_or_long_error(num, name, arg); + break; + case ZPP_ERROR_WRONG_CLASS_OR_LONG_OR_NULL: + zend_wrong_parameter_class_or_long_or_null_error(num, name, arg); + break; + case ZPP_ERROR_WRONG_ARG: + zend_wrong_parameter_type_error(num, expected_type, arg); + break; case ZPP_ERROR_UNEXPECTED_EXTRA_NAMED: zend_unexpected_extra_named_error(); break; @@ -280,6 +286,26 @@ ZEND_API ZEND_COLD void ZEND_FASTCALL zend_wrong_parameter_class_or_null_error(u } /* }}} */ +ZEND_API ZEND_COLD void ZEND_FASTCALL zend_wrong_parameter_class_or_long_error(uint32_t num, const char *name, zval *arg) /* {{{ */ +{ + if (EG(exception)) { + return; + } + + zend_argument_type_error(num, "must be of type %s|int, %s given", name, zend_zval_type_name(arg)); +} +/* }}} */ + +ZEND_API ZEND_COLD void ZEND_FASTCALL zend_wrong_parameter_class_or_long_or_null_error(uint32_t num, const char *name, zval *arg) /* {{{ */ +{ + if (EG(exception)) { + return; + } + + zend_argument_type_error(num, "must be of type %s|int|null, %s given", name, zend_zval_type_name(arg)); +} +/* }}} */ + ZEND_API ZEND_COLD void ZEND_FASTCALL zend_wrong_parameter_class_or_string_error(uint32_t num, const char *name, zval *arg) /* {{{ */ { if (EG(exception)) { diff --git a/Zend/zend_API.h b/Zend/zend_API.h index 226ca60d1b..da9a57d5c6 100644 --- a/Zend/zend_API.h +++ b/Zend/zend_API.h @@ -1209,6 +1209,8 @@ static zend_always_inline zval *zend_try_array_init(zval *zv) _(Z_EXPECTED_STRING_OR_NULL, "of type ?string") \ _(Z_EXPECTED_ARRAY, "of type array") \ _(Z_EXPECTED_ARRAY_OR_NULL, "of type ?array") \ + _(Z_EXPECTED_ARRAY_OR_LONG, "of type array|int") \ + _(Z_EXPECTED_ARRAY_OR_LONG_OR_NULL, "of type array|int|null") \ _(Z_EXPECTED_ITERABLE, "of type iterable") \ _(Z_EXPECTED_ITERABLE_OR_NULL, "of type ?iterable") \ _(Z_EXPECTED_FUNC, "a valid callback") \ @@ -1248,6 +1250,8 @@ ZEND_API ZEND_COLD void ZEND_FASTCALL zend_wrong_parameter_error(int error_code, ZEND_API ZEND_COLD void ZEND_FASTCALL zend_wrong_parameter_type_error(uint32_t num, zend_expected_type expected_type, zval *arg); ZEND_API ZEND_COLD void ZEND_FASTCALL zend_wrong_parameter_class_error(uint32_t num, const char *name, zval *arg); ZEND_API ZEND_COLD void ZEND_FASTCALL zend_wrong_parameter_class_or_null_error(uint32_t num, const char *name, zval *arg); +ZEND_API ZEND_COLD void ZEND_FASTCALL zend_wrong_parameter_class_or_long_error(uint32_t num, const char *name, zval *arg); +ZEND_API ZEND_COLD void ZEND_FASTCALL zend_wrong_parameter_class_or_long_or_null_error(uint32_t num, const char *name, zval *arg); ZEND_API ZEND_COLD void ZEND_FASTCALL zend_wrong_parameter_class_or_string_error(uint32_t num, const char *name, zval *arg); ZEND_API ZEND_COLD void ZEND_FASTCALL zend_wrong_parameter_class_or_string_or_null_error(uint32_t num, const char *name, zval *arg); ZEND_API ZEND_COLD void ZEND_FASTCALL zend_wrong_callback_error(uint32_t num, char *error); @@ -1261,11 +1265,13 @@ ZEND_API ZEND_COLD void zend_argument_value_error(uint32_t arg_num, const char * #define ZPP_ERROR_WRONG_CALLBACK 2 #define ZPP_ERROR_WRONG_CLASS 3 #define ZPP_ERROR_WRONG_CLASS_OR_NULL 4 -#define ZPP_ERROR_WRONG_ARG 5 -#define ZPP_ERROR_WRONG_COUNT 6 -#define ZPP_ERROR_WRONG_CLASS_OR_STRING 7 -#define ZPP_ERROR_WRONG_CLASS_OR_STRING_OR_NULL 8 -#define ZPP_ERROR_UNEXPECTED_EXTRA_NAMED 9 +#define ZPP_ERROR_WRONG_CLASS_OR_STRING 5 +#define ZPP_ERROR_WRONG_CLASS_OR_STRING_OR_NULL 6 +#define ZPP_ERROR_WRONG_CLASS_OR_LONG 7 +#define ZPP_ERROR_WRONG_CLASS_OR_LONG_OR_NULL 8 +#define ZPP_ERROR_WRONG_ARG 9 +#define ZPP_ERROR_WRONG_COUNT 10 +#define ZPP_ERROR_UNEXPECTED_EXTRA_NAMED 11 #define ZEND_PARSE_PARAMETERS_START_EX(flags, min_num_args, max_num_args) do { \ const int _flags = (flags); \ @@ -1675,6 +1681,21 @@ ZEND_API ZEND_COLD void zend_argument_value_error(uint32_t arg_num, const char * #define Z_PARAM_OBJ_OF_CLASS_OR_NULL(dest, _ce) \ Z_PARAM_OBJ_OF_CLASS_EX(dest, _ce, 1, 0) + +#define Z_PARAM_OBJ_OF_CLASS_OR_LONG_EX(dest_obj, _ce, dest_long, is_null, allow_null) \ + Z_PARAM_PROLOGUE(0, 0); \ + if (UNEXPECTED(!zend_parse_arg_obj_or_long(_arg, &dest_obj, _ce, &dest_long, &is_null, allow_null))) { \ + _error = ZSTR_VAL((_ce)->name); \ + _error_code = allow_null ? ZPP_ERROR_WRONG_CLASS_OR_LONG_OR_NULL : ZPP_ERROR_WRONG_CLASS_OR_LONG; \ + break; \ + } + +#define Z_PARAM_OBJ_OF_CLASS_OR_LONG(dest_obj, _ce, dest_long) \ + Z_PARAM_OBJ_OF_CLASS_OR_LONG_EX(dest_obj, _ce, dest_long, _dummy, 0) + +#define Z_PARAM_OBJ_OF_CLASS_OR_LONG_OR_NULL(dest_obj, _ce, dest_long, is_null) \ + Z_PARAM_OBJ_OF_CLASS_OR_LONG_EX(dest_obj, _ce, dest_long, is_null, 1) + /* old "p" */ #define Z_PARAM_PATH_EX2(dest, dest_len, check_null, deref, separate) \ Z_PARAM_PROLOGUE(deref, separate); \ @@ -2028,6 +2049,29 @@ static zend_always_inline bool zend_parse_arg_array_ht(zval *arg, HashTable **de return 1; } +static zend_always_inline bool zend_parse_arg_array_ht_or_long( + zval *arg, HashTable **dest_ht, zend_long *dest_long, zend_bool *is_null, bool allow_null +) { + if (allow_null) { + *is_null = 0; + } + + if (EXPECTED(Z_TYPE_P(arg) == IS_ARRAY)) { + *dest_ht = Z_ARRVAL_P(arg); + } else if (EXPECTED(Z_TYPE_P(arg) == IS_LONG)) { + *dest_ht = NULL; + *dest_long = Z_LVAL_P(arg); + } else if (allow_null && EXPECTED(Z_TYPE_P(arg) == IS_NULL)) { + *dest_ht = NULL; + *is_null = 1; + } else { + *dest_ht = NULL; + return zend_parse_arg_long_slow(arg, dest_long); + } + + return 1; +} + static zend_always_inline bool zend_parse_arg_object(zval *arg, zval **dest, zend_class_entry *ce, bool check_null) { if (EXPECTED(Z_TYPE_P(arg) == IS_OBJECT) && @@ -2054,6 +2098,29 @@ static zend_always_inline bool zend_parse_arg_obj(zval *arg, zend_object **dest, return 1; } +static zend_always_inline bool zend_parse_arg_obj_or_long( + zval *arg, zend_object **dest_obj, zend_class_entry *ce, zend_long *dest_long, zend_bool *is_null, bool allow_null +) { + if (allow_null) { + *is_null = 0; + } + + if (EXPECTED(Z_TYPE_P(arg) == IS_OBJECT) && EXPECTED(instanceof_function(Z_OBJCE_P(arg), ce) != 0)) { + *dest_obj = Z_OBJ_P(arg); + } else if (EXPECTED(Z_TYPE_P(arg) == IS_LONG)) { + *dest_obj = NULL; + *dest_long = Z_LVAL_P(arg); + } else if (allow_null && EXPECTED(Z_TYPE_P(arg) == IS_NULL)) { + *dest_obj = NULL; + *is_null = 1; + } else { + *dest_obj = NULL; + return zend_parse_arg_long_slow(arg, dest_long); + } + + return 1; +} + static zend_always_inline bool zend_parse_arg_resource(zval *arg, zval **dest, bool check_null) { if (EXPECTED(Z_TYPE_P(arg) == IS_RESOURCE)) { diff --git a/ext/filter/filter.c b/ext/filter/filter.c index 37fac29de9..4aa9368213 100644 --- a/ext/filter/filter.c +++ b/ext/filter/filter.c @@ -524,31 +524,31 @@ PHP_FUNCTION(filter_has_var) } /* }}} */ -static void php_filter_call(zval *filtered, zend_long filter, zval *filter_args, const int copy, zend_long filter_flags) /* {{{ */ -{ +static void php_filter_call( + zval *filtered, zend_long filter, HashTable *filter_args_ht, zend_long filter_args_long, + const int copy, zend_long filter_flags +) /* {{{ */ { zval *options = NULL; zval *option; char *charset = NULL; - if (filter_args && Z_TYPE_P(filter_args) != IS_ARRAY) { - zend_long lval = zval_get_long(filter_args); - + if (!filter_args_ht) { if (filter != -1) { /* handler for array apply */ /* filter_args is the filter_flags */ - filter_flags = lval; + filter_flags = filter_args_long; if (!(filter_flags & FILTER_REQUIRE_ARRAY || filter_flags & FILTER_FORCE_ARRAY)) { filter_flags |= FILTER_REQUIRE_SCALAR; } } else { - filter = lval; + filter = filter_args_long; } - } else if (filter_args) { - if ((option = zend_hash_str_find(Z_ARRVAL_P(filter_args), "filter", sizeof("filter") - 1)) != NULL) { + } else { + if ((option = zend_hash_str_find(filter_args_ht, "filter", sizeof("filter") - 1)) != NULL) { filter = zval_get_long(option); } - if ((option = zend_hash_str_find(Z_ARRVAL_P(filter_args), "flags", sizeof("flags") - 1)) != NULL) { + if ((option = zend_hash_str_find(filter_args_ht, "flags", sizeof("flags") - 1)) != NULL) { filter_flags = zval_get_long(option); if (!(filter_flags & FILTER_REQUIRE_ARRAY || filter_flags & FILTER_FORCE_ARRAY)) { @@ -556,7 +556,7 @@ static void php_filter_call(zval *filtered, zend_long filter, zval *filter_args, } } - if ((option = zend_hash_str_find_deref(Z_ARRVAL_P(filter_args), "options", sizeof("options") - 1)) != NULL) { + if ((option = zend_hash_str_find_deref(filter_args_ht, "options", sizeof("options") - 1)) != NULL) { if (filter != FILTER_CALLBACK) { if (Z_TYPE_P(option) == IS_ARRAY) { options = option; @@ -601,21 +601,19 @@ static void php_filter_call(zval *filtered, zend_long filter, zval *filter_args, } /* }}} */ -static void php_filter_array_handler(zval *input, zval *op, zval *return_value, zend_bool add_empty) /* {{{ */ -{ +static void php_filter_array_handler(zval *input, HashTable *op_ht, zend_long op_long, + zval *return_value, zend_bool add_empty +) /* {{{ */ { zend_string *arg_key; zval *tmp, *arg_elm; - if (!op) { + if (!op_ht) { ZVAL_DUP(return_value, input); - php_filter_call(return_value, FILTER_DEFAULT, NULL, 0, FILTER_REQUIRE_ARRAY); - } else if (Z_TYPE_P(op) == IS_LONG) { - ZVAL_DUP(return_value, input); - php_filter_call(return_value, Z_LVAL_P(op), NULL, 0, FILTER_REQUIRE_ARRAY); - } else if (Z_TYPE_P(op) == IS_ARRAY) { + php_filter_call(return_value, -1, NULL, op_long, 0, FILTER_REQUIRE_ARRAY); + } else { array_init(return_value); - ZEND_HASH_FOREACH_STR_KEY_VAL(Z_ARRVAL_P(op), arg_key, arg_elm) { + ZEND_HASH_FOREACH_STR_KEY_VAL(op_ht, arg_key, arg_elm) { if (arg_key == NULL) { zend_argument_type_error(2, "must contain only string keys"); RETURN_THROWS(); @@ -632,12 +630,14 @@ static void php_filter_array_handler(zval *input, zval *op, zval *return_value, zval nval; ZVAL_DEREF(tmp); ZVAL_DUP(&nval, tmp); - php_filter_call(&nval, -1, arg_elm, 0, FILTER_REQUIRE_SCALAR); + php_filter_call(&nval, -1, + Z_TYPE_P(arg_elm) == IS_ARRAY ? Z_ARRVAL_P(arg_elm) : NULL, + Z_TYPE_P(arg_elm) == IS_ARRAY ? 0 : zval_get_long(arg_elm), + 0, FILTER_REQUIRE_SCALAR + ); zend_hash_update(Z_ARRVAL_P(return_value), arg_key, &nval); } } ZEND_HASH_FOREACH_END(); - } else { - RETURN_FALSE; } } /* }}} */ @@ -646,15 +646,21 @@ static void php_filter_array_handler(zval *input, zval *op, zval *return_value, PHP_FUNCTION(filter_input) { zend_long fetch_from, filter = FILTER_DEFAULT; - zval *filter_args = NULL, *tmp; - zval *input = NULL; + zval *input = NULL, *tmp; zend_string *var; + HashTable *filter_args_ht = NULL; + zend_long filter_args_long = 0; - if (zend_parse_parameters(ZEND_NUM_ARGS(), "lS|lz", &fetch_from, &var, &filter, &filter_args) == FAILURE) { - RETURN_THROWS(); - } + ZEND_PARSE_PARAMETERS_START(2, 4) + Z_PARAM_LONG(fetch_from) + Z_PARAM_STR(var) + Z_PARAM_OPTIONAL + Z_PARAM_LONG(filter) + Z_PARAM_ARRAY_HT_OR_LONG(filter_args_ht, filter_args_long) + ZEND_PARSE_PARAMETERS_END(); if (!PHP_FILTER_ID_EXISTS(filter)) { + php_error_docref(NULL, E_WARNING, "Unknown filter with ID " ZEND_LONG_FMT, filter); RETURN_FALSE; } @@ -666,16 +672,17 @@ PHP_FUNCTION(filter_input) if (!input || (tmp = zend_hash_find(Z_ARRVAL_P(input), var)) == NULL) { zend_long filter_flags = 0; zval *option, *opt, *def; - if (filter_args) { - if (Z_TYPE_P(filter_args) == IS_LONG) { - filter_flags = Z_LVAL_P(filter_args); - } else if (Z_TYPE_P(filter_args) == IS_ARRAY && (option = zend_hash_str_find(Z_ARRVAL_P(filter_args), "flags", sizeof("flags") - 1)) != NULL) { + if (!filter_args_ht) { + filter_flags = filter_args_long; + } else { + if ((option = zend_hash_str_find(filter_args_ht, "flags", sizeof("flags") - 1)) != NULL) { filter_flags = zval_get_long(option); } - if (Z_TYPE_P(filter_args) == IS_ARRAY && - (opt = zend_hash_str_find_deref(Z_ARRVAL_P(filter_args), "options", sizeof("options") - 1)) != NULL && + + if ((opt = zend_hash_str_find_deref(filter_args_ht, "options", sizeof("options") - 1)) != NULL && Z_TYPE_P(opt) == IS_ARRAY && - (def = zend_hash_str_find_deref(Z_ARRVAL_P(opt), "default", sizeof("default") - 1)) != NULL) { + (def = zend_hash_str_find_deref(Z_ARRVAL_P(opt), "default", sizeof("default") - 1)) != NULL + ) { ZVAL_COPY(return_value, def); return; } @@ -695,7 +702,7 @@ PHP_FUNCTION(filter_input) ZVAL_DUP(return_value, tmp); - php_filter_call(return_value, filter, filter_args, 1, FILTER_REQUIRE_SCALAR); + php_filter_call(return_value, filter, filter_args_ht, filter_args_long, 1, FILTER_REQUIRE_SCALAR); } /* }}} */ @@ -703,19 +710,25 @@ PHP_FUNCTION(filter_input) PHP_FUNCTION(filter_var) { zend_long filter = FILTER_DEFAULT; - zval *filter_args = NULL, *data; + zval *data; + HashTable *filter_args_ht = NULL; + zend_long filter_args_long = 0; - if (zend_parse_parameters(ZEND_NUM_ARGS(), "z|lz", &data, &filter, &filter_args) == FAILURE) { - RETURN_THROWS(); - } + ZEND_PARSE_PARAMETERS_START(1, 3) + Z_PARAM_ZVAL(data) + Z_PARAM_OPTIONAL + Z_PARAM_LONG(filter) + Z_PARAM_ARRAY_HT_OR_LONG(filter_args_ht, filter_args_long) + ZEND_PARSE_PARAMETERS_END(); if (!PHP_FILTER_ID_EXISTS(filter)) { + php_error_docref(NULL, E_WARNING, "Unknown filter with ID " ZEND_LONG_FMT, filter); RETURN_FALSE; } ZVAL_DUP(return_value, data); - php_filter_call(return_value, filter, filter_args, 1, FILTER_REQUIRE_SCALAR); + php_filter_call(return_value, filter, filter_args_ht, filter_args_long, 1, FILTER_REQUIRE_SCALAR); } /* }}} */ @@ -723,14 +736,20 @@ PHP_FUNCTION(filter_var) PHP_FUNCTION(filter_input_array) { zend_long fetch_from; - zval *array_input = NULL, *op = NULL; + zval *array_input = NULL; zend_bool add_empty = 1; - - if (zend_parse_parameters(ZEND_NUM_ARGS(), "l|zb", &fetch_from, &op, &add_empty) == FAILURE) { - RETURN_THROWS(); - } - - if (op && (Z_TYPE_P(op) != IS_ARRAY) && !(Z_TYPE_P(op) == IS_LONG && PHP_FILTER_ID_EXISTS(Z_LVAL_P(op)))) { + HashTable *op_ht = NULL; + zend_long op_long = FILTER_DEFAULT; + + ZEND_PARSE_PARAMETERS_START(1, 3) + Z_PARAM_LONG(fetch_from) + Z_PARAM_OPTIONAL + Z_PARAM_ARRAY_HT_OR_LONG(op_ht, op_long) + Z_PARAM_BOOL(add_empty) + ZEND_PARSE_PARAMETERS_END(); + + if (!op_ht && !PHP_FILTER_ID_EXISTS(op_long)) { + php_error_docref(NULL, E_WARNING, "Unknown filter with ID " ZEND_LONG_FMT, op_long); RETURN_FALSE; } @@ -742,12 +761,10 @@ PHP_FUNCTION(filter_input_array) if (!array_input) { zend_long filter_flags = 0; zval *option; - if (op) { - if (Z_TYPE_P(op) == IS_LONG) { - filter_flags = Z_LVAL_P(op); - } else if (Z_TYPE_P(op) == IS_ARRAY && (option = zend_hash_str_find(Z_ARRVAL_P(op), "flags", sizeof("flags") - 1)) != NULL) { - filter_flags = zval_get_long(option); - } + if (op_long) { + filter_flags = op_long; + } else if (op_ht && (option = zend_hash_str_find(op_ht, "flags", sizeof("flags") - 1)) != NULL) { + filter_flags = zval_get_long(option); } /* The FILTER_NULL_ON_FAILURE flag inverts the usual return values of @@ -762,25 +779,31 @@ PHP_FUNCTION(filter_input_array) } } - php_filter_array_handler(array_input, op, return_value, add_empty); + php_filter_array_handler(array_input, op_ht, op_long, return_value, add_empty); } /* }}} */ /* {{{ Returns an array with all arguments defined in 'definition'. */ PHP_FUNCTION(filter_var_array) { - zval *array_input = NULL, *op = NULL; + zval *array_input = NULL; zend_bool add_empty = 1; - - if (zend_parse_parameters(ZEND_NUM_ARGS(), "a|zb", &array_input, &op, &add_empty) == FAILURE) { - RETURN_THROWS(); - } - - if (op && (Z_TYPE_P(op) != IS_ARRAY) && !(Z_TYPE_P(op) == IS_LONG && PHP_FILTER_ID_EXISTS(Z_LVAL_P(op)))) { + HashTable *op_ht = NULL; + zend_long op_long = FILTER_DEFAULT; + + ZEND_PARSE_PARAMETERS_START(1, 3) + Z_PARAM_ARRAY(array_input) + Z_PARAM_OPTIONAL + Z_PARAM_ARRAY_HT_OR_LONG(op_ht, op_long) + Z_PARAM_BOOL(add_empty) + ZEND_PARSE_PARAMETERS_END(); + + if (!op_ht && !PHP_FILTER_ID_EXISTS(op_long)) { + php_error_docref(NULL, E_WARNING, "Unknown filter with ID " ZEND_LONG_FMT, op_long); RETURN_FALSE; } - php_filter_array_handler(array_input, op, return_value, add_empty); + php_filter_array_handler(array_input, op_ht, op_long, return_value, add_empty); } /* }}} */ diff --git a/ext/filter/filter.stub.php b/ext/filter/filter.stub.php index e8e6b0fbdd..56f926b913 100644 --- a/ext/filter/filter.stub.php +++ b/ext/filter/filter.stub.php @@ -4,17 +4,13 @@ function filter_has_var(int $type, string $variable_name): bool {} -/** @param array|int $options */ -function filter_input(int $type, string $variable_name, int $filter = FILTER_DEFAULT, $options = null): mixed {} +function filter_input(int $type, string $variable_name, int $filter = FILTER_DEFAULT, array|int $options = 0): mixed {} -/** @param array|int $options */ -function filter_var(mixed $variable, int $filter = FILTER_DEFAULT, $options = null): mixed {} +function filter_var(mixed $variable, int $filter = FILTER_DEFAULT, array|int $options = 0): mixed {} -/** @param array|int $options */ -function filter_input_array(int $type, $options = FILTER_DEFAULT, bool $add_empty = true): array|false|null {} +function filter_input_array(int $type, array|int $options = FILTER_DEFAULT, bool $add_empty = true): array|false|null {} -/** @param array|int $options */ -function filter_var_array(array $data, $options = FILTER_DEFAULT, bool $add_empty = true): array|false|null {} +function filter_var_array(array $data, array|int $options = FILTER_DEFAULT, bool $add_empty = true): array|false|null {} function filter_list(): array {} diff --git a/ext/filter/filter_arginfo.h b/ext/filter/filter_arginfo.h index 00d1809250..bb3ab54666 100644 --- a/ext/filter/filter_arginfo.h +++ b/ext/filter/filter_arginfo.h @@ -1,5 +1,5 @@ /* This is a generated file, edit the .stub.php file instead. - * Stub hash: 54d4bb809e05c73a1a16174bce578377f7cd8f31 */ + * Stub hash: dae0cf8beeb47a996123cffd3b429482047d42c1 */ ZEND_BEGIN_ARG_WITH_RETURN_TYPE_INFO_EX(arginfo_filter_has_var, 0, 2, _IS_BOOL, 0) ZEND_ARG_TYPE_INFO(0, type, IS_LONG, 0) @@ -10,24 +10,24 @@ ZEND_BEGIN_ARG_WITH_RETURN_TYPE_INFO_EX(arginfo_filter_input, 0, 2, IS_MIXED, 0) ZEND_ARG_TYPE_INFO(0, type, IS_LONG, 0) ZEND_ARG_TYPE_INFO(0, variable_name, IS_STRING, 0) ZEND_ARG_TYPE_INFO_WITH_DEFAULT_VALUE(0, filter, IS_LONG, 0, "FILTER_DEFAULT") - ZEND_ARG_INFO_WITH_DEFAULT_VALUE(0, options, "null") + ZEND_ARG_TYPE_MASK(0, options, MAY_BE_ARRAY|MAY_BE_LONG, "0") ZEND_END_ARG_INFO() ZEND_BEGIN_ARG_WITH_RETURN_TYPE_INFO_EX(arginfo_filter_var, 0, 1, IS_MIXED, 0) ZEND_ARG_TYPE_INFO(0, variable, IS_MIXED, 0) ZEND_ARG_TYPE_INFO_WITH_DEFAULT_VALUE(0, filter, IS_LONG, 0, "FILTER_DEFAULT") - ZEND_ARG_INFO_WITH_DEFAULT_VALUE(0, options, "null") + ZEND_ARG_TYPE_MASK(0, options, MAY_BE_ARRAY|MAY_BE_LONG, "0") ZEND_END_ARG_INFO() ZEND_BEGIN_ARG_WITH_RETURN_TYPE_MASK_EX(arginfo_filter_input_array, 0, 1, MAY_BE_ARRAY|MAY_BE_FALSE|MAY_BE_NULL) ZEND_ARG_TYPE_INFO(0, type, IS_LONG, 0) - ZEND_ARG_INFO_WITH_DEFAULT_VALUE(0, options, "FILTER_DEFAULT") + ZEND_ARG_TYPE_MASK(0, options, MAY_BE_ARRAY|MAY_BE_LONG, "FILTER_DEFAULT") ZEND_ARG_TYPE_INFO_WITH_DEFAULT_VALUE(0, add_empty, _IS_BOOL, 0, "true") ZEND_END_ARG_INFO() ZEND_BEGIN_ARG_WITH_RETURN_TYPE_MASK_EX(arginfo_filter_var_array, 0, 1, MAY_BE_ARRAY|MAY_BE_FALSE|MAY_BE_NULL) ZEND_ARG_TYPE_INFO(0, data, IS_ARRAY, 0) - ZEND_ARG_INFO_WITH_DEFAULT_VALUE(0, options, "FILTER_DEFAULT") + ZEND_ARG_TYPE_MASK(0, options, MAY_BE_ARRAY|MAY_BE_LONG, "FILTER_DEFAULT") ZEND_ARG_TYPE_INFO_WITH_DEFAULT_VALUE(0, add_empty, _IS_BOOL, 0, "true") ZEND_END_ARG_INFO() diff --git a/ext/filter/tests/010.phpt b/ext/filter/tests/010.phpt index 46b6044668..802f817e98 100644 --- a/ext/filter/tests/010.phpt +++ b/ext/filter/tests/010.phpt @@ -17,7 +17,7 @@ var_dump(filter_var(1, 0, array())); echo "Done\n"; ?> ---EXPECT-- +--EXPECTF-- array(7) { [0]=> int(1) @@ -55,6 +55,10 @@ array(7) { string(1) "1" string(1) "1" string(1) "1" + +Warning: filter_var(): Unknown filter with ID -1 in %s on line %d bool(false) + +Warning: filter_var(): Unknown filter with ID 0 in %s on line %d bool(false) Done diff --git a/ext/filter/tests/011.phpt b/ext/filter/tests/011.phpt index 1b2a2ec357..5c00f895fd 100644 --- a/ext/filter/tests/011.phpt +++ b/ext/filter/tests/011.phpt @@ -14,7 +14,11 @@ ini_set('html_errors', false); var_dump(filter_input(INPUT_GET, "a", FILTER_SANITIZE_STRIPPED)); var_dump(filter_input(INPUT_GET, "b", FILTER_SANITIZE_URL)); var_dump(filter_input(INPUT_GET, "a", FILTER_SANITIZE_SPECIAL_CHARS, array(1,2,3,4,5))); -var_dump(filter_input(INPUT_GET, "b", FILTER_VALIDATE_FLOAT, new stdClass)); +try { + filter_input(INPUT_GET, "b", FILTER_VALIDATE_FLOAT, new stdClass); +} catch (TypeError $exception) { + echo $exception->getMessage() . "\n"; +} var_dump(filter_input(INPUT_POST, "c", FILTER_SANITIZE_STRIPPED, array(5,6,7,8))); var_dump(filter_input(INPUT_POST, "d", FILTER_VALIDATE_FLOAT)); var_dump(filter_input(INPUT_POST, "c", FILTER_SANITIZE_SPECIAL_CHARS)); @@ -22,13 +26,11 @@ var_dump(filter_input(INPUT_POST, "d", FILTER_VALIDATE_INT)); echo "Done\n"; ?> ---EXPECTF-- +--EXPECT-- string(4) "test" string(18) "http://example.com" string(27) "<b>test</b>" - -Notice: Object of class stdClass could not be converted to int in %s011.php on line %d -bool(false) +filter_input(): Argument #4 ($options) must be of type array|int, stdClass given string(6) "string" float(12345.7) string(29) "<p>string</p>" diff --git a/ext/filter/tests/039.phpt b/ext/filter/tests/039.phpt index f5a1cf2fe7..ec6f075bc3 100644 --- a/ext/filter/tests/039.phpt +++ b/ext/filter/tests/039.phpt @@ -10,20 +10,41 @@ var_dump(filter_var_array(array())); var_dump(filter_var_array(array(1,"blah"=>"hoho"))); var_dump(filter_var_array(array(), -1)); var_dump(filter_var_array(array(), 1000000)); -var_dump(filter_var_array(array(), "")); + +try { + filter_var_array(array(), ""); +} catch (TypeError $exception) { + echo $exception->getMessage() . "\n"; +} echo "-- (2)\n"; var_dump(filter_var_array(array(""=>""), -1)); var_dump(filter_var_array(array(""=>""), 1000000)); -var_dump(filter_var_array(array(""=>""), "")); + +try { + filter_var_array(array(""=>""), ""); +} catch (TypeError $exception) { + echo $exception->getMessage() . "\n"; +} echo "-- (3)\n"; var_dump(filter_var_array(array("aaa"=>"bbb"), -1)); var_dump(filter_var_array(array("aaa"=>"bbb"), 1000000)); -var_dump(filter_var_array(array("aaa"=>"bbb"), "")); + +try { + filter_var_array(array("aaa"=>"bbb"), ""); +} catch (TypeError $exception) { + echo $exception->getMessage() . "\n"; +} echo "-- (4)\n"; -var_dump(filter_var_array(array(), new stdclass)); + +try { + filter_var_array(array(), new stdclass); +} catch (TypeError $exception) { + echo $exception->getMessage() . "\n"; +} + var_dump(filter_var_array(array(), array())); var_dump(filter_var_array(array(), array("var_name"=>1))); var_dump(filter_var_array(array(), array("var_name"=>-1))); @@ -50,12 +71,16 @@ var_dump(filter_var_array($a, $b)); var_dump($a, $b); $a = array(""=>""); $b = ""; -var_dump(filter_var_array($a, $b)); +try { + filter_var_array($a, $b); +} catch (TypeError $exception) { + echo $exception->getMessage() . "\n"; +} var_dump($a, $b); echo "Done\n"; ?> ---EXPECT-- +--EXPECTF-- -- (1) array(0) { } @@ -65,19 +90,31 @@ array(2) { ["blah"]=> string(4) "hoho" } + +Warning: filter_var_array(): Unknown filter with ID -1 in %s on line %d bool(false) + +Warning: filter_var_array(): Unknown filter with ID 1000000 in %s on line %d bool(false) -bool(false) +filter_var_array(): Argument #2 ($options) must be of type array|int, string given -- (2) + +Warning: filter_var_array(): Unknown filter with ID -1 in %s on line %d bool(false) + +Warning: filter_var_array(): Unknown filter with ID 1000000 in %s on line %d bool(false) -bool(false) +filter_var_array(): Argument #2 ($options) must be of type array|int, string given -- (3) + +Warning: filter_var_array(): Unknown filter with ID -1 in %s on line %d bool(false) + +Warning: filter_var_array(): Unknown filter with ID 1000000 in %s on line %d bool(false) -bool(false) +filter_var_array(): Argument #2 ($options) must be of type array|int, string given -- (4) -bool(false) +filter_var_array(): Argument #2 ($options) must be of type array|int, stdClass given array(0) { } array(1) { @@ -95,19 +132,23 @@ array(1) { -- (5) filter_var_array(): Argument #2 ($options) cannot contain empty keys filter_var_array(): Argument #2 ($options) cannot contain empty keys + +Warning: filter_var_array(): Unknown filter with ID -1 in %s on line %d bool(false) array(1) { [""]=> string(0) "" } int(-1) + +Warning: filter_var_array(): Unknown filter with ID 100000 in %s on line %d bool(false) array(1) { [""]=> string(0) "" } int(100000) -bool(false) +filter_var_array(): Argument #2 ($options) must be of type array|int, string given array(1) { [""]=> string(0) "" diff --git a/ext/filter/tests/057.phpt b/ext/filter/tests/057.phpt index fc4c3a824c..7c57a2670b 100644 --- a/ext/filter/tests/057.phpt +++ b/ext/filter/tests/057.phpt @@ -5,20 +5,44 @@ filter_input_array() and filter_var_array() with invalid $definition arguments --FILE-- <?php foreach (array(null, true, false, 1, "", new stdClass) as $invalid) { - var_dump(filter_input_array(INPUT_POST, $invalid)); - var_dump(filter_var_array(array(), $invalid)); + try { + var_dump(filter_input_array(INPUT_POST, $invalid)); + } catch (TypeError $exception) { + echo $exception->getMessage() . "\n"; + } + + try { + var_dump(filter_var_array(array(), $invalid)); + } catch (TypeError $exception) { + echo $exception->getMessage() . "\n"; + } } ?> ---EXPECT-- -bool(false) -bool(false) -bool(false) -bool(false) +--EXPECTF-- +Warning: filter_input_array(): Unknown filter with ID 0 in %s on line %d bool(false) + +Warning: filter_var_array(): Unknown filter with ID 0 in %s on line %d bool(false) + +Warning: filter_input_array(): Unknown filter with ID 1 in %s on line %d bool(false) + +Warning: filter_var_array(): Unknown filter with ID 1 in %s on line %d bool(false) + +Warning: filter_input_array(): Unknown filter with ID 0 in %s on line %d bool(false) + +Warning: filter_var_array(): Unknown filter with ID 0 in %s on line %d bool(false) + +Warning: filter_input_array(): Unknown filter with ID 1 in %s on line %d bool(false) + +Warning: filter_var_array(): Unknown filter with ID 1 in %s on line %d bool(false) +filter_input_array(): Argument #2 ($options) must be of type array|int, string given +filter_var_array(): Argument #2 ($options) must be of type array|int, string given +filter_input_array(): Argument #2 ($options) must be of type array|int, stdClass given +filter_var_array(): Argument #2 ($options) must be of type array|int, stdClass given diff --git a/ext/intl/calendar/calendar_class.cpp b/ext/intl/calendar/calendar_class.cpp index 06f64f5e11..a46ef62e68 100644 --- a/ext/intl/calendar/calendar_class.cpp +++ b/ext/intl/calendar/calendar_class.cpp @@ -57,9 +57,9 @@ U_CFUNC void calendar_object_create(zval *object, calendar_object_construct(object, calendar); } -U_CFUNC Calendar *calendar_fetch_native_calendar(zval *object) +U_CFUNC Calendar *calendar_fetch_native_calendar(zend_object *object) { - Calendar_object *co = Z_INTL_CALENDAR_P(object); + Calendar_object *co = php_intl_calendar_fetch_object(object); return co->ucal; } diff --git a/ext/intl/calendar/calendar_class.h b/ext/intl/calendar/calendar_class.h index a4d5236307..c301cda481 100644 --- a/ext/intl/calendar/calendar_class.h +++ b/ext/intl/calendar/calendar_class.h @@ -61,14 +61,13 @@ static inline Calendar_object *php_intl_calendar_fetch_object(zend_object *obj) void calendar_object_create(zval *object, Calendar *calendar); -Calendar *calendar_fetch_native_calendar(zval *object); +Calendar *calendar_fetch_native_calendar(zend_object *object); void calendar_object_construct(zval *object, Calendar *calendar); void calendar_register_IntlCalendar_class(void); -extern zend_class_entry *Calendar_ce_ptr, - *GregorianCalendar_ce_ptr; +extern zend_class_entry *Calendar_ce_ptr, *GregorianCalendar_ce_ptr; extern zend_object_handlers Calendar_handlers; diff --git a/ext/intl/dateformat/dateformat.stub.php b/ext/intl/dateformat/dateformat.stub.php index 5d77e07555..53cda18560 100644 --- a/ext/intl/dateformat/dateformat.stub.php +++ b/ext/intl/dateformat/dateformat.stub.php @@ -12,11 +12,10 @@ class IntlDateFormatter /** * @param IntlTimeZone|DateTimeZone|string|null $timezone - * @param IntlCalendar|int|null $calendar * @return IntlDateFormatter|null * @alias datefmt_create */ - public static function create(?string $locale, int $datetype, int $timetype, $timezone = null, $calendar = null, string $pattern = "") {} + public static function create(?string $locale, int $datetype, int $timetype, $timezone = null, IntlCalendar|int|null $calendar = null, string $pattern = "") {} /** * @return int|false @@ -37,11 +36,10 @@ class IntlDateFormatter public function getCalendar() {} /** - * @param IntlCalendar|int|null $which * @return bool * @alias datefmt_set_calendar */ - public function setCalendar($which) {} + public function setCalendar(IntlCalendar|int|null $which) {} /** * @return string|false diff --git a/ext/intl/dateformat/dateformat_arginfo.h b/ext/intl/dateformat/dateformat_arginfo.h index d94c886003..7a468d4fda 100644 --- a/ext/intl/dateformat/dateformat_arginfo.h +++ b/ext/intl/dateformat/dateformat_arginfo.h @@ -1,5 +1,5 @@ /* This is a generated file, edit the .stub.php file instead. - * Stub hash: 1b018a6b473db965a89c4ce9ebce3133d8d304db */ + * Stub hash: 6e7935cd23cd9bba625cf65d08d8e3796f938d74 */ ZEND_BEGIN_ARG_INFO_EX(arginfo_class_IntlDateFormatter___construct, 0, 0, 3) ZEND_ARG_TYPE_INFO(0, locale, IS_STRING, 1) @@ -10,7 +10,14 @@ ZEND_BEGIN_ARG_INFO_EX(arginfo_class_IntlDateFormatter___construct, 0, 0, 3) ZEND_ARG_TYPE_INFO_WITH_DEFAULT_VALUE(0, pattern, IS_STRING, 0, "\"\"") ZEND_END_ARG_INFO() -#define arginfo_class_IntlDateFormatter_create arginfo_class_IntlDateFormatter___construct +ZEND_BEGIN_ARG_INFO_EX(arginfo_class_IntlDateFormatter_create, 0, 0, 3) + ZEND_ARG_TYPE_INFO(0, locale, IS_STRING, 1) + ZEND_ARG_TYPE_INFO(0, datetype, IS_LONG, 0) + ZEND_ARG_TYPE_INFO(0, timetype, IS_LONG, 0) + ZEND_ARG_INFO_WITH_DEFAULT_VALUE(0, timezone, "null") + ZEND_ARG_OBJ_TYPE_MASK(0, calendar, IntlCalendar, MAY_BE_LONG|MAY_BE_NULL, "null") + ZEND_ARG_TYPE_INFO_WITH_DEFAULT_VALUE(0, pattern, IS_STRING, 0, "\"\"") +ZEND_END_ARG_INFO() ZEND_BEGIN_ARG_INFO_EX(arginfo_class_IntlDateFormatter_getDateType, 0, 0, 0) ZEND_END_ARG_INFO() @@ -20,7 +27,7 @@ ZEND_END_ARG_INFO() #define arginfo_class_IntlDateFormatter_getCalendar arginfo_class_IntlDateFormatter_getDateType ZEND_BEGIN_ARG_INFO_EX(arginfo_class_IntlDateFormatter_setCalendar, 0, 0, 1) - ZEND_ARG_INFO(0, which) + ZEND_ARG_OBJ_TYPE_MASK(0, which, IntlCalendar, MAY_BE_LONG|MAY_BE_NULL, NULL) ZEND_END_ARG_INFO() #define arginfo_class_IntlDateFormatter_getTimeZoneId arginfo_class_IntlDateFormatter_getDateType diff --git a/ext/intl/dateformat/dateformat_attrcpp.cpp b/ext/intl/dateformat/dateformat_attrcpp.cpp index fdf61d8500..343ef170d2 100644 --- a/ext/intl/dateformat/dateformat_attrcpp.cpp +++ b/ext/intl/dateformat/dateformat_attrcpp.cpp @@ -156,12 +156,22 @@ U_CFUNC PHP_FUNCTION(datefmt_get_calendar_object) /* {{{ Set formatter's calendar. */ U_CFUNC PHP_FUNCTION(datefmt_set_calendar) { - zval *calendar_zv; + zend_object *calendar_obj; + zend_long calendar_long; + zend_bool calendar_is_null; DATE_FORMAT_METHOD_INIT_VARS; - if (zend_parse_method_parameters(ZEND_NUM_ARGS(), getThis(), "Oz", - &object, IntlDateFormatter_ce_ptr, &calendar_zv) == FAILURE) { - RETURN_THROWS(); + object = getThis(); + + if (object) { + ZEND_PARSE_PARAMETERS_START(1, 1) + Z_PARAM_OBJ_OF_CLASS_OR_LONG_OR_NULL(calendar_obj, Calendar_ce_ptr, calendar_long, calendar_is_null) + ZEND_PARSE_PARAMETERS_END(); + } else { + ZEND_PARSE_PARAMETERS_START(2, 2) + Z_PARAM_OBJECT_OF_CLASS(object, IntlDateFormatter_ce_ptr) + Z_PARAM_OBJ_OF_CLASS_OR_LONG_OR_NULL(calendar_obj, Calendar_ce_ptr, calendar_long, calendar_is_null) + ZEND_PARSE_PARAMETERS_END(); } DATE_FORMAT_METHOD_FETCH_OBJECT; @@ -174,9 +184,9 @@ U_CFUNC PHP_FUNCTION(datefmt_set_calendar) // because we would have lost modifiers such as @calendar. We // must store the requested locale on object creation - if (datefmt_process_calendar_arg(calendar_zv, locale, - "datefmt_set_calendar", INTL_DATA_ERROR_P(dfo), cal, cal_type, - cal_owned) == FAILURE) { + if (datefmt_process_calendar_arg(calendar_obj, calendar_long, calendar_is_null, locale, + "datefmt_set_calendar", INTL_DATA_ERROR_P(dfo), cal, cal_type, cal_owned) == FAILURE + ) { RETURN_FALSE; } diff --git a/ext/intl/dateformat/dateformat_create.cpp b/ext/intl/dateformat/dateformat_create.cpp index a75719c0f4..43e113fab1 100644 --- a/ext/intl/dateformat/dateformat_create.cpp +++ b/ext/intl/dateformat/dateformat_create.cpp @@ -26,6 +26,8 @@ extern "C" { #include "php_intl.h" #include "dateformat_create.h" #include "dateformat_class.h" +#define USE_CALENDAR_POINTER 1 +#include "../calendar/calendar_class.h" #define USE_TIMEZONE_POINTER 1 #include "../timezone/timezone_class.h" #include "../intl_convert.h" @@ -43,16 +45,18 @@ extern "C" { UDAT_PATTERN == (i)) /* {{{ */ -static int datefmt_ctor(INTERNAL_FUNCTION_PARAMETERS) +static zend_result datefmt_ctor(INTERNAL_FUNCTION_PARAMETERS) { zval *object; - const char *locale_str; + char *locale_str; size_t locale_len = 0; Locale locale; zend_long date_type = 0; zend_long time_type = 0; - zval *calendar_zv = NULL; - Calendar *calendar = NULL; + zend_object *calendar_obj = NULL; + zend_long calendar_long; + zend_bool calendar_is_null = 1; + Calendar *cal = NULL; zend_long calendar_type; bool calendar_owned; zval *timezone_zv = NULL; @@ -66,18 +70,21 @@ static int datefmt_ctor(INTERNAL_FUNCTION_PARAMETERS) intl_error_reset(NULL); object = return_value; - /* Parse parameters. */ - if (zend_parse_parameters(ZEND_NUM_ARGS(), "s!ll|zzs", - &locale_str, &locale_len, &date_type, &time_type, &timezone_zv, - &calendar_zv, &pattern_str, &pattern_str_len) == FAILURE) { - return FAILURE; - } + + ZEND_PARSE_PARAMETERS_START(3, 6) + Z_PARAM_STRING_OR_NULL(locale_str, locale_len) + Z_PARAM_LONG(date_type) + Z_PARAM_LONG(time_type) + Z_PARAM_OPTIONAL + Z_PARAM_ZVAL(timezone_zv) + Z_PARAM_OBJ_OF_CLASS_OR_LONG_OR_NULL(calendar_obj, Calendar_ce_ptr, calendar_long, calendar_is_null) + Z_PARAM_STRING_OR_NULL(pattern_str, pattern_str_len) + ZEND_PARSE_PARAMETERS_END_EX(return FAILURE); DATE_FORMAT_METHOD_FETCH_OBJECT_NO_CHECK; if (DATE_FORMAT_OBJECT(dfo) != NULL) { - intl_errors_set(INTL_DATA_ERROR_P(dfo), U_ILLEGAL_ARGUMENT_ERROR, - "datefmt_create: cannot call constructor twice", 0); + intl_errors_set(INTL_DATA_ERROR_P(dfo), U_ILLEGAL_ARGUMENT_ERROR, "datefmt_create: cannot call constructor twice", 0); return FAILURE; } @@ -87,20 +94,19 @@ static int datefmt_ctor(INTERNAL_FUNCTION_PARAMETERS) } if (!INTL_UDATE_FMT_OK(time_type)) { intl_error_set(NULL, U_ILLEGAL_ARGUMENT_ERROR, "datefmt_create: invalid time format style", 0); - return FAILURE; +return FAILURE; } INTL_CHECK_LOCALE_LEN_OR_FAILURE(locale_len); if (locale_len == 0) { - locale_str = intl_locale_get_default(); + locale_str = (char *) intl_locale_get_default(); } locale = Locale::createFromName(locale_str); /* process calendar */ - if (datefmt_process_calendar_arg(calendar_zv, locale, "datefmt_create", - INTL_DATA_ERROR_P(dfo), calendar, calendar_type, - calendar_owned) - == FAILURE) { + if (datefmt_process_calendar_arg(calendar_obj, calendar_long, calendar_is_null, locale, "datefmt_create", + INTL_DATA_ERROR_P(dfo), cal, calendar_type, calendar_owned) == FAILURE + ) { goto error; } @@ -143,10 +149,10 @@ static int datefmt_ctor(INTERNAL_FUNCTION_PARAMETERS) if (!U_FAILURE(INTL_DATA_ERROR_CODE(dfo))) { DateFormat *df = (DateFormat*)DATE_FORMAT_OBJECT(dfo); if (calendar_owned) { - df->adoptCalendar(calendar); + df->adoptCalendar(cal); calendar_owned = false; } else { - df->setCalendar(*calendar); + df->setCalendar(*cal); } if (timezone != NULL) { @@ -171,8 +177,8 @@ error: if (timezone != NULL && DATE_FORMAT_OBJECT(dfo) == NULL) { delete timezone; } - if (calendar != NULL && calendar_owned) { - delete calendar; + if (cal != NULL && calendar_owned) { + delete cal; } return U_FAILURE(intl_error_get_code(NULL)) ? FAILURE : SUCCESS; @@ -183,7 +189,7 @@ error: U_CFUNC PHP_FUNCTION( datefmt_create ) { object_init_ex( return_value, IntlDateFormatter_ce_ptr ); - if (datefmt_ctor(INTERNAL_FUNCTION_PARAM_PASSTHRU) == FAILURE) { + if (datefmt_ctor(INTERNAL_FUNCTION_PARAM_PASSTHRU) == FAILURE) { zval_ptr_dtor(return_value); RETURN_NULL(); } diff --git a/ext/intl/dateformat/dateformat_format_object.cpp b/ext/intl/dateformat/dateformat_format_object.cpp index 9723006b15..d569eb935d 100644 --- a/ext/intl/dateformat/dateformat_format_object.cpp +++ b/ext/intl/dateformat/dateformat_format_object.cpp @@ -158,7 +158,7 @@ U_CFUNC PHP_FUNCTION(datefmt_format_object) zend_class_entry *instance_ce = Z_OBJCE_P(object); if (instanceof_function(instance_ce, Calendar_ce_ptr)) { - Calendar *obj_cal = calendar_fetch_native_calendar(object); + Calendar *obj_cal = calendar_fetch_native_calendar(Z_OBJ_P(object)); if (obj_cal == NULL) { intl_error_set(NULL, U_ILLEGAL_ARGUMENT_ERROR, "datefmt_format_object: bad IntlCalendar instance: " diff --git a/ext/intl/dateformat/dateformat_helpers.cpp b/ext/intl/dateformat/dateformat_helpers.cpp index 69332e931c..46c909bf95 100644 --- a/ext/intl/dateformat/dateformat_helpers.cpp +++ b/ext/intl/dateformat/dateformat_helpers.cpp @@ -28,28 +28,22 @@ extern "C" { using icu::GregorianCalendar; -int datefmt_process_calendar_arg(zval* calendar_zv, - Locale const& locale, - const char *func_name, - intl_error *err, - Calendar*& cal, - zend_long& cal_int_type, - bool& calendar_owned) -{ +int datefmt_process_calendar_arg( + zend_object *calendar_obj, zend_long calendar_long, zend_bool calendar_is_null, Locale const& locale, + const char *func_name, intl_error *err, Calendar*& cal, zend_long& cal_int_type, bool& calendar_owned +) { char *msg; UErrorCode status = UErrorCode(); - if (calendar_zv == NULL || Z_TYPE_P(calendar_zv) == IS_NULL) { - + if (calendar_is_null) { // default requested cal = new GregorianCalendar(locale, status); calendar_owned = true; cal_int_type = UCAL_GREGORIAN; - } else if (Z_TYPE_P(calendar_zv) == IS_LONG) { - - zend_long v = Z_LVAL_P(calendar_zv); + } else if (!calendar_obj) { + zend_long v = calendar_long; if (v != (zend_long)UCAL_TRADITIONAL && v != (zend_long)UCAL_GREGORIAN) { spprintf(&msg, 0, "%s: Invalid value for calendar type; it must be " "one of IntlDateFormatter::TRADITIONAL (locale's default " @@ -66,12 +60,10 @@ int datefmt_process_calendar_arg(zval* calendar_zv, } calendar_owned = true; - cal_int_type = Z_LVAL_P(calendar_zv); - - } else if (Z_TYPE_P(calendar_zv) == IS_OBJECT && - instanceof_function(Z_OBJCE_P(calendar_zv), Calendar_ce_ptr)) { + cal_int_type = calendar_long; - cal = calendar_fetch_native_calendar(calendar_zv); + } else if (calendar_obj) { + cal = calendar_fetch_native_calendar(calendar_obj); if (cal == NULL) { spprintf(&msg, 0, "%s: Found unconstructed IntlCalendar object", func_name); diff --git a/ext/intl/dateformat/dateformat_helpers.h b/ext/intl/dateformat/dateformat_helpers.h index 0c88977015..1f2d7eb32e 100644 --- a/ext/intl/dateformat/dateformat_helpers.h +++ b/ext/intl/dateformat/dateformat_helpers.h @@ -30,12 +30,9 @@ using icu::Locale; using icu::Calendar; using icu::DateFormat; -int datefmt_process_calendar_arg(zval* calendar_zv, - Locale const& locale, - const char *func_name, - intl_error *err, - Calendar*& cal, - zend_long& cal_int_type, - bool& calendar_owned); +int datefmt_process_calendar_arg( + zend_object *calendar_obj, zend_long calendar_long, zend_bool calendar_is_null, Locale const& locale, + const char *func_name, intl_error *err, Calendar*& cal, zend_long& cal_int_type, bool& calendar_owned +); #endif /* DATEFORMAT_HELPERS_H */ diff --git a/ext/intl/php_intl.stub.php b/ext/intl/php_intl.stub.php index 7662004f30..f2a1af1c2e 100644 --- a/ext/intl/php_intl.stub.php +++ b/ext/intl/php_intl.stub.php @@ -153,11 +153,8 @@ function intl_error_name(int $error_code): string {} /* dateformat */ -/** - * @param IntlTimeZone|DateTimeZone|string|null $timezone - * @param IntlCalendar|int|null $calendar - */ -function datefmt_create(?string $locale, int $datetype, int $timetype, $timezone = null, $calendar = null, string $pattern = ""): ?IntlDateFormatter {} +/** @param IntlTimeZone|DateTimeZone|string|null $timezone */ +function datefmt_create(?string $locale, int $datetype, int $timetype, $timezone = null, IntlCalendar|int|null $calendar = null, string $pattern = ""): ?IntlDateFormatter {} function datefmt_get_datetype(IntlDateFormatter $df): int|false {} @@ -165,8 +162,7 @@ function datefmt_get_timetype(IntlDateFormatter $df): int|false {} function datefmt_get_calendar(IntlDateFormatter $df): int|false {} -/** @param IntlCalendar|int|null $which */ -function datefmt_set_calendar(IntlDateFormatter $df, $which): bool {} +function datefmt_set_calendar(IntlDateFormatter $df, IntlCalendar|int|null $which): bool {} function datefmt_get_timezone_id(IntlDateFormatter $df): string|false {} diff --git a/ext/intl/php_intl_arginfo.h b/ext/intl/php_intl_arginfo.h index 3917187a5c..32f098d0bb 100644 --- a/ext/intl/php_intl_arginfo.h +++ b/ext/intl/php_intl_arginfo.h @@ -1,5 +1,5 @@ /* This is a generated file, edit the .stub.php file instead. - * Stub hash: fdc7c500ddc5bc560ec54b7ce12d5961a4697a63 */ + * Stub hash: 324b7ae3eaab4777117c1c6963bc841088e6b998 */ ZEND_BEGIN_ARG_WITH_RETURN_OBJ_INFO_EX(arginfo_intlcal_create_instance, 0, 0, IntlCalendar, 1) ZEND_ARG_INFO_WITH_DEFAULT_VALUE(0, timeZone, "null") @@ -281,7 +281,7 @@ ZEND_BEGIN_ARG_WITH_RETURN_OBJ_INFO_EX(arginfo_datefmt_create, 0, 3, IntlDateFor ZEND_ARG_TYPE_INFO(0, datetype, IS_LONG, 0) ZEND_ARG_TYPE_INFO(0, timetype, IS_LONG, 0) ZEND_ARG_INFO_WITH_DEFAULT_VALUE(0, timezone, "null") - ZEND_ARG_INFO_WITH_DEFAULT_VALUE(0, calendar, "null") + ZEND_ARG_OBJ_TYPE_MASK(0, calendar, IntlCalendar, MAY_BE_LONG|MAY_BE_NULL, "null") ZEND_ARG_TYPE_INFO_WITH_DEFAULT_VALUE(0, pattern, IS_STRING, 0, "\"\"") ZEND_END_ARG_INFO() @@ -295,7 +295,7 @@ ZEND_END_ARG_INFO() ZEND_BEGIN_ARG_WITH_RETURN_TYPE_INFO_EX(arginfo_datefmt_set_calendar, 0, 2, _IS_BOOL, 0) ZEND_ARG_OBJ_INFO(0, df, IntlDateFormatter, 0) - ZEND_ARG_INFO(0, which) + ZEND_ARG_OBJ_TYPE_MASK(0, which, IntlCalendar, MAY_BE_LONG|MAY_BE_NULL, NULL) ZEND_END_ARG_INFO() ZEND_BEGIN_ARG_WITH_RETURN_TYPE_MASK_EX(arginfo_datefmt_get_timezone_id, 0, 1, MAY_BE_STRING|MAY_BE_FALSE) diff --git a/ext/intl/tests/dateformat___construct_bad_tz_cal.phpt b/ext/intl/tests/dateformat___construct_bad_tz_cal.phpt index 086bc01340..928c30b922 100644 --- a/ext/intl/tests/dateformat___construct_bad_tz_cal.phpt +++ b/ext/intl/tests/dateformat___construct_bad_tz_cal.phpt @@ -26,7 +26,7 @@ try { } try { var_dump(new IntlDateFormatter(NULL, 0, 0, NULL, new stdclass)); -} catch (IntlException $e) { +} catch (TypeError $e) { print_exception($e); } ?> @@ -35,4 +35,4 @@ Exception: IntlDateFormatter::__construct(): datefmt_create: No such time zone: Exception: IntlDateFormatter::__construct(): datefmt_create: Invalid value for calendar type; it must be one of IntlDateFormatter::TRADITIONAL (locale's default calendar) or IntlDateFormatter::GREGORIAN. Alternatively, it can be an IntlCalendar object in %s on line %d -Exception: IntlDateFormatter::__construct(): datefmt_create: Invalid calendar argument; should be an integer or an IntlCalendar instance in %s on line %d +Exception: IntlDateFormatter::__construct(): Argument #5 ($calendar) must be of type IntlCalendar|int|null, stdClass given in %s on line %d diff --git a/ext/session/session.c b/ext/session/session.c index 4f12e447ba..79b82f90f7 100644 --- a/ext/session/session.c +++ b/ext/session/session.c @@ -1674,7 +1674,8 @@ PHPAPI void session_adapt_url(const char *url, size_t url_len, char **new_url, s Set session cookie parameters */ PHP_FUNCTION(session_set_cookie_params) { - zval *lifetime_or_options = NULL; + HashTable *options_ht; + zend_long lifetime_long; zend_string *lifetime = NULL, *path = NULL, *domain = NULL, *samesite = NULL; zend_bool secure = 0, secure_null = 1; zend_bool httponly = 0, httponly_null = 1; @@ -1687,12 +1688,12 @@ PHP_FUNCTION(session_set_cookie_params) } ZEND_PARSE_PARAMETERS_START(1, 5) - Z_PARAM_ZVAL(lifetime_or_options) + Z_PARAM_ARRAY_HT_OR_LONG(options_ht, lifetime_long) Z_PARAM_OPTIONAL - Z_PARAM_STR(path) - Z_PARAM_STR(domain) - Z_PARAM_BOOL_EX(secure, secure_null, 1, 0) - Z_PARAM_BOOL_EX(httponly, httponly_null, 1, 0) + Z_PARAM_STR_OR_NULL(path) + Z_PARAM_STR_OR_NULL(domain) + Z_PARAM_BOOL_OR_NULL(secure, secure_null) + Z_PARAM_BOOL_OR_NULL(httponly, httponly_null) ZEND_PARSE_PARAMETERS_END(); if (PS(session_status) == php_session_active) { @@ -1705,20 +1706,31 @@ PHP_FUNCTION(session_set_cookie_params) RETURN_FALSE; } - if (Z_TYPE_P(lifetime_or_options) == IS_ARRAY) { + if (options_ht) { zend_string *key; zval *value; if (path) { - path = NULL; - domain = NULL; - secure_null = 1; - httponly_null = 1; - php_error_docref(NULL, E_WARNING, "Cannot pass arguments after the options array"); - RETURN_FALSE; + zend_argument_value_error(2, "must be null when argument #1 ($lifetime_or_options) is an array"); + RETURN_THROWS(); + } + + if (domain) { + zend_argument_value_error(3, "must be null when argument #1 ($lifetime_or_options) is an array"); + RETURN_THROWS(); + } + + if (!secure_null) { + zend_argument_value_error(4, "must be null when argument #1 ($lifetime_or_options) is an array"); + RETURN_THROWS(); + } + + if (!httponly_null) { + zend_argument_value_error(5, "must be null when argument #1 ($lifetime_or_options) is an array"); + RETURN_THROWS(); } - ZEND_HASH_FOREACH_STR_KEY_VAL(Z_ARRVAL_P(lifetime_or_options), key, value) { + ZEND_HASH_FOREACH_STR_KEY_VAL(options_ht, key, value) { if (key) { ZVAL_DEREF(value); if(!strcasecmp("lifetime", ZSTR_VAL(key))) { @@ -1754,7 +1766,7 @@ PHP_FUNCTION(session_set_cookie_params) RETURN_THROWS(); } } else { - lifetime = zval_get_string(lifetime_or_options); + lifetime = zend_long_to_str(lifetime_long); } /* Exception during string conversion */ diff --git a/ext/session/session.stub.php b/ext/session/session.stub.php index b8f9f33eba..36a0b983b9 100644 --- a/ext/session/session.stub.php +++ b/ext/session/session.stub.php @@ -49,8 +49,7 @@ function session_cache_limiter(?string $cache_limiter = null): string|false {} function session_cache_expire(?int $new_cache_expire = null): int|false {} -/** @param int|array $lifetime_or_options */ -function session_set_cookie_params($lifetime_or_options, string $path = UNKNOWN, string $domain = "", ?bool $secure = null, ?bool $httponly = null): bool {} +function session_set_cookie_params(array|int $lifetime_or_options, ?string $path = null, ?string $domain = null, ?bool $secure = null, ?bool $httponly = null): bool {} function session_start(array $options = []): bool {} diff --git a/ext/session/session_arginfo.h b/ext/session/session_arginfo.h index c47dee6315..f29a0df86b 100644 --- a/ext/session/session_arginfo.h +++ b/ext/session/session_arginfo.h @@ -1,5 +1,5 @@ /* This is a generated file, edit the .stub.php file instead. - * Stub hash: 22b829d3cdd092c393c924f323cd19bea1517579 */ + * Stub hash: 9bdf602c14822b13553a5214a415e312c21cd30c */ ZEND_BEGIN_ARG_WITH_RETURN_TYPE_MASK_EX(arginfo_session_name, 0, 0, MAY_BE_STRING|MAY_BE_FALSE) ZEND_ARG_TYPE_INFO_WITH_DEFAULT_VALUE(0, name, IS_STRING, 1, "null") @@ -78,9 +78,9 @@ ZEND_BEGIN_ARG_WITH_RETURN_TYPE_MASK_EX(arginfo_session_cache_expire, 0, 0, MAY_ ZEND_END_ARG_INFO() ZEND_BEGIN_ARG_WITH_RETURN_TYPE_INFO_EX(arginfo_session_set_cookie_params, 0, 1, _IS_BOOL, 0) - ZEND_ARG_INFO(0, lifetime_or_options) - ZEND_ARG_TYPE_INFO(0, path, IS_STRING, 0) - ZEND_ARG_TYPE_INFO_WITH_DEFAULT_VALUE(0, domain, IS_STRING, 0, "\"\"") + ZEND_ARG_TYPE_MASK(0, lifetime_or_options, MAY_BE_ARRAY|MAY_BE_LONG, NULL) + ZEND_ARG_TYPE_INFO_WITH_DEFAULT_VALUE(0, path, IS_STRING, 1, "null") + ZEND_ARG_TYPE_INFO_WITH_DEFAULT_VALUE(0, domain, IS_STRING, 1, "null") ZEND_ARG_TYPE_INFO_WITH_DEFAULT_VALUE(0, secure, _IS_BOOL, 1, "null") ZEND_ARG_TYPE_INFO_WITH_DEFAULT_VALUE(0, httponly, _IS_BOOL, 1, "null") ZEND_END_ARG_INFO() diff --git a/ext/session/tests/session_set_cookie_params_variation7.phpt b/ext/session/tests/session_set_cookie_params_variation7.phpt index 25feabf1fd..cdc56554e3 100644 --- a/ext/session/tests/session_set_cookie_params_variation7.phpt +++ b/ext/session/tests/session_set_cookie_params_variation7.phpt @@ -40,7 +40,13 @@ var_dump(session_set_cookie_params(["lifetime" => 42])); var_dump(ini_get("session.cookie_lifetime")); var_dump(ini_get("session.cookie_path")); -var_dump(session_set_cookie_params(["path" => "newpath/"], "arg after options array")); + +try { + session_set_cookie_params(["path" => "newpath/"], "arg after options array"); +} catch (ValueError $exception) { + echo $exception->getMessage() . "\n"; +} + var_dump(ini_get("session.cookie_path")); echo "Done"; @@ -63,8 +69,6 @@ string(1) "0" bool(true) string(2) "42" string(1) "/" - -Warning: session_set_cookie_params(): Cannot pass arguments after the options array in %s on line %d -bool(false) +session_set_cookie_params(): Argument #2 ($path) must be null when argument #1 ($lifetime_or_options) is an array string(1) "/" Done diff --git a/ext/standard/basic_functions.stub.php b/ext/standard/basic_functions.stub.php index 8e3996e072..281d8167b8 100755 --- a/ext/standard/basic_functions.stub.php +++ b/ext/standard/basic_functions.stub.php @@ -502,11 +502,9 @@ function header(string $string, bool $replace = true, int $http_response_code = function header_remove(?string $name = null): void {} -/** @param array|int $expires_or_options */ -function setrawcookie(string $name, string $value = '', $expires_or_options = 0, string $path = '', string $domain = '', bool $secure = false, bool $httponly = false): bool {} +function setrawcookie(string $name, string $value = '', array|int $expires_or_options = 0, string $path = '', string $domain = '', bool $secure = false, bool $httponly = false): bool {} -/** @param array|int $expires_or_options */ -function setcookie(string $name, string $value = '', $expires_or_options = 0, string $path = '', string $domain = '', bool $secure = false, bool $httponly = false): bool {} +function setcookie(string $name, string $value = '', array|int $expires_or_options = 0, string $path = '', string $domain = '', bool $secure = false, bool $httponly = false): bool {} function http_response_code(int $response_code = 0): int|bool {} @@ -612,11 +610,7 @@ function chunk_split(string $str, int $chunklen = 76, string $ending = "\r\n"): function substr(string $str, int $start, ?int $length = null): string|false {} -/** - * @param array|int $start - * @param array|int|null $length - */ -function substr_replace(array|string $str, string|array $replace, $start, $length = null): string|array|false {} +function substr_replace(array|string $str, array|string $replace, array|int $start, array|int|null $length = null): string|array|false {} function quotemeta(string $str): string {} diff --git a/ext/standard/basic_functions_arginfo.h b/ext/standard/basic_functions_arginfo.h index 5943429517..5097ca53fc 100755 --- 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: 251fc9f272492ab76c4a1a1dabcd768269cf1bde */ + * Stub hash: d1bcbdfe71bdc57680abe391d1ef2859538615c2 */ 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) @@ -746,7 +746,7 @@ ZEND_END_ARG_INFO() ZEND_BEGIN_ARG_WITH_RETURN_TYPE_INFO_EX(arginfo_setrawcookie, 0, 1, _IS_BOOL, 0) ZEND_ARG_TYPE_INFO(0, name, IS_STRING, 0) ZEND_ARG_TYPE_INFO_WITH_DEFAULT_VALUE(0, value, IS_STRING, 0, "\'\'") - ZEND_ARG_INFO_WITH_DEFAULT_VALUE(0, expires_or_options, "0") + ZEND_ARG_TYPE_MASK(0, expires_or_options, MAY_BE_ARRAY|MAY_BE_LONG, "0") ZEND_ARG_TYPE_INFO_WITH_DEFAULT_VALUE(0, path, IS_STRING, 0, "\'\'") ZEND_ARG_TYPE_INFO_WITH_DEFAULT_VALUE(0, domain, IS_STRING, 0, "\'\'") ZEND_ARG_TYPE_INFO_WITH_DEFAULT_VALUE(0, secure, _IS_BOOL, 0, "false") @@ -935,9 +935,9 @@ ZEND_END_ARG_INFO() ZEND_BEGIN_ARG_WITH_RETURN_TYPE_MASK_EX(arginfo_substr_replace, 0, 3, MAY_BE_STRING|MAY_BE_ARRAY|MAY_BE_FALSE) ZEND_ARG_TYPE_MASK(0, str, MAY_BE_ARRAY|MAY_BE_STRING, NULL) - ZEND_ARG_TYPE_MASK(0, replace, MAY_BE_STRING|MAY_BE_ARRAY, NULL) - ZEND_ARG_INFO(0, start) - ZEND_ARG_INFO_WITH_DEFAULT_VALUE(0, length, "null") + ZEND_ARG_TYPE_MASK(0, replace, MAY_BE_ARRAY|MAY_BE_STRING, NULL) + ZEND_ARG_TYPE_MASK(0, start, MAY_BE_ARRAY|MAY_BE_LONG, NULL) + ZEND_ARG_TYPE_MASK(0, length, MAY_BE_ARRAY|MAY_BE_LONG|MAY_BE_NULL, "null") ZEND_END_ARG_INFO() #define arginfo_quotemeta arginfo_base64_encode diff --git a/ext/standard/head.c b/ext/standard/head.c index 18cb0c4f62..36f64fcb4d 100644 --- a/ext/standard/head.c +++ b/ext/standard/head.c @@ -192,13 +192,13 @@ PHPAPI zend_result php_setcookie(zend_string *name, zend_string *value, time_t e return result; } -static zend_result php_head_parse_cookie_options_array(zval *options, zend_long *expires, zend_string **path, +static zend_result php_head_parse_cookie_options_array(HashTable *options, zend_long *expires, zend_string **path, zend_string **domain, zend_bool *secure, zend_bool *httponly, zend_string **samesite) { zend_string *key; zval *value; - ZEND_HASH_FOREACH_STR_KEY_VAL(Z_ARRVAL_P(options), key, value) { + ZEND_HASH_FOREACH_STR_KEY_VAL(options, key, value) { if (!key) { zend_value_error("%s(): option array cannot have numeric keys", get_active_function_name()); return FAILURE; @@ -225,36 +225,33 @@ static zend_result php_head_parse_cookie_options_array(zval *options, zend_long static void php_setcookie_common(INTERNAL_FUNCTION_PARAMETERS, bool is_raw) { - /* to handle overloaded function array|int */ - zval *expires_or_options = NULL; - zend_string *name, *value = NULL, *path = NULL, *domain = NULL, *samesite = NULL; + HashTable *options = NULL; zend_long expires = 0; + zend_string *name, *value = NULL, *path = NULL, *domain = NULL, *samesite = NULL; zend_bool secure = 0, httponly = 0; ZEND_PARSE_PARAMETERS_START(1, 7) Z_PARAM_STR(name) Z_PARAM_OPTIONAL Z_PARAM_STR(value) - Z_PARAM_ZVAL(expires_or_options) + Z_PARAM_ARRAY_HT_OR_LONG(options, expires) Z_PARAM_STR(path) Z_PARAM_STR(domain) Z_PARAM_BOOL(secure) Z_PARAM_BOOL(httponly) ZEND_PARSE_PARAMETERS_END(); - if (expires_or_options) { - if (Z_TYPE_P(expires_or_options) == IS_ARRAY) { - if (UNEXPECTED(ZEND_NUM_ARGS() > 3)) { - zend_argument_count_error("%s(): Expects exactly 3 arguments when argument #3 " - "($expires_or_options) is an array", get_active_function_name()); - RETURN_THROWS(); - } - if (FAILURE == php_head_parse_cookie_options_array(expires_or_options, &expires, &path, - &domain, &secure, &httponly, &samesite)) { - goto cleanup; - } - } else { - expires = zval_get_long(expires_or_options); + if (options) { + if (UNEXPECTED(ZEND_NUM_ARGS() > 3)) { + zend_argument_count_error("%s(): Expects exactly 3 arguments when argument #3 " + "($expires_or_options) is an array", get_active_function_name()); + RETURN_THROWS(); + } + + if (FAILURE == php_head_parse_cookie_options_array(options, &expires, &path, + &domain, &secure, &httponly, &samesite) + ) { + goto cleanup; } } @@ -264,7 +261,7 @@ static void php_setcookie_common(INTERNAL_FUNCTION_PARAMETERS, bool is_raw) RETVAL_FALSE; } - if (expires_or_options && Z_TYPE_P(expires_or_options) == IS_ARRAY) { + if (options) { cleanup: if (path) { zend_string_release(path); diff --git a/ext/standard/string.c b/ext/standard/string.c index 9fd7e5f454..b3d357baa8 100644 --- a/ext/standard/string.c +++ b/ext/standard/string.c @@ -2237,8 +2237,11 @@ PHP_FUNCTION(substr_replace) { zend_string *str, *repl_str; HashTable *str_ht, *repl_ht; - zval *from; - zval *len = NULL; + HashTable *from_ht; + zend_long from_long; + HashTable *len_ht = NULL; + zend_long len_long; + zend_bool len_is_null = 1; zend_long l = 0; zend_long f; zend_string *result; @@ -2248,39 +2251,26 @@ PHP_FUNCTION(substr_replace) ZEND_PARSE_PARAMETERS_START(3, 4) Z_PARAM_ARRAY_HT_OR_STR(str_ht, str) Z_PARAM_ARRAY_HT_OR_STR(repl_ht, repl_str) - Z_PARAM_ZVAL(from) + Z_PARAM_ARRAY_HT_OR_LONG(from_ht, from_long) Z_PARAM_OPTIONAL - Z_PARAM_ZVAL_OR_NULL(len) + Z_PARAM_ARRAY_HT_OR_LONG_OR_NULL(len_ht, len_long, len_is_null) ZEND_PARSE_PARAMETERS_END(); - if (Z_TYPE_P(from) != IS_ARRAY) { - convert_to_long_ex(from); - if (EG(exception)) { - RETURN_THROWS(); - } - } - - if (len) { - if (Z_TYPE_P(len) != IS_ARRAY) { - convert_to_long_ex(len); - l = Z_LVAL_P(len); - } - } else { + if (len_is_null) { if (str) { l = ZSTR_LEN(str); } + } else if (!len_ht) { + l = len_long; } if (str) { - if ( - (!len && Z_TYPE_P(from) == IS_ARRAY) || - (len && Z_TYPE_P(from) != Z_TYPE_P(len)) - ) { + if ((len_is_null && from_ht) || (!len_is_null && (from_ht == NULL) != (len_ht == NULL))) { php_error_docref(NULL, E_WARNING, "'start' and 'length' should be of same type - numerical or array "); RETURN_STR_COPY(str); } - if (len && Z_TYPE_P(from) == IS_ARRAY) { - if (zend_hash_num_elements(Z_ARRVAL_P(from)) != zend_hash_num_elements(Z_ARRVAL_P(len))) { + if (!len_is_null && from_ht) { + if (zend_hash_num_elements(from_ht) != zend_hash_num_elements(len_ht)) { php_error_docref(NULL, E_WARNING, "'start' and 'length' should have the same number of elements"); RETURN_STR_COPY(str); } @@ -2288,8 +2278,8 @@ PHP_FUNCTION(substr_replace) } if (str) { - if (Z_TYPE_P(from) != IS_ARRAY) { - f = Z_LVAL_P(from); + if (!from_ht) { + f = from_long; /* if "from" position is negative, count start position from the end * of the string @@ -2364,15 +2354,15 @@ PHP_FUNCTION(substr_replace) zend_string *tmp_orig_str; zend_string *orig_str = zval_get_tmp_string(tmp_str, &tmp_orig_str); - if (Z_TYPE_P(from) == IS_ARRAY) { - while (from_idx < Z_ARRVAL_P(from)->nNumUsed) { - tmp_from = &Z_ARRVAL_P(from)->arData[from_idx].val; + if (from_ht) { + while (from_idx < from_ht->nNumUsed) { + tmp_from = &from_ht->arData[from_idx].val; if (Z_TYPE_P(tmp_from) != IS_UNDEF) { break; } from_idx++; } - if (from_idx < Z_ARRVAL_P(from)->nNumUsed) { + if (from_idx < from_ht->nNumUsed) { f = zval_get_long(tmp_from); if (f < 0) { @@ -2388,7 +2378,7 @@ PHP_FUNCTION(substr_replace) f = 0; } } else { - f = Z_LVAL_P(from); + f = from_long; if (f < 0) { f = (zend_long)ZSTR_LEN(orig_str) + f; if (f < 0) { @@ -2399,22 +2389,22 @@ PHP_FUNCTION(substr_replace) } } - if (len && Z_TYPE_P(len) == IS_ARRAY) { - while (len_idx < Z_ARRVAL_P(len)->nNumUsed) { - tmp_len = &Z_ARRVAL_P(len)->arData[len_idx].val; + if (len_ht) { + while (len_idx < len_ht->nNumUsed) { + tmp_len = &len_ht->arData[len_idx].val; if (Z_TYPE_P(tmp_len) != IS_UNDEF) { break; } len_idx++; } - if (len_idx < Z_ARRVAL_P(len)->nNumUsed) { + if (len_idx < len_ht->nNumUsed) { l = zval_get_long(tmp_len); len_idx++; } else { l = ZSTR_LEN(orig_str); } - } else if (len) { - l = Z_LVAL_P(len); + } else if (!len_is_null) { + l = len_long; } else { l = ZSTR_LEN(orig_str); } |