summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--Zend/zend_API.c10
-rw-r--r--Zend/zend_API.h2
-rw-r--r--Zend/zend_compile.h16
-rw-r--r--Zend/zend_execute.c230
-rw-r--r--Zend/zend_vm_def.h75
-rw-r--r--Zend/zend_vm_execute.h197
6 files changed, 280 insertions, 250 deletions
diff --git a/Zend/zend_API.c b/Zend/zend_API.c
index 1ef695dd4e..c626a8ddd7 100644
--- a/Zend/zend_API.c
+++ b/Zend/zend_API.c
@@ -151,7 +151,7 @@ ZEND_API int zend_copy_parameters_array(int param_count, zval *argument_array) /
ZEND_API void zend_wrong_param_count(void) /* {{{ */
{
- if (EX_PREV_USES_STRICT_TYPES()) {
+ if (ZEND_ARG_USES_STRICT_TYPES()) {
zend_wrong_param_count_ex(1);
} else {
zend_wrong_param_count_ex(0);
@@ -802,7 +802,7 @@ ZEND_API int zend_parse_parameters_ex(int flags, int num_args, const char *type_
va_list va;
int retval;
- if (EX_PREV_USES_STRICT_TYPES()) {
+ if (ZEND_ARG_USES_STRICT_TYPES()) {
flags |= ZEND_PARSE_PARAMS_STRICT;
}
@@ -822,7 +822,7 @@ ZEND_API int zend_parse_parameters(int num_args, const char *type_spec, ...) /*
int retval;
int flags = 0;
- if (EX_PREV_USES_STRICT_TYPES()) {
+ if (ZEND_ARG_USES_STRICT_TYPES()) {
flags |= ZEND_PARSE_PARAMS_STRICT;
}
@@ -851,7 +851,7 @@ ZEND_API int zend_parse_method_parameters(int num_args, zval *this_ptr, const ch
* wrong branch here. */
zend_bool is_method = EG(current_execute_data)->func->common.scope != NULL;
- if (EX_PREV_USES_STRICT_TYPES()) {
+ if (ZEND_ARG_USES_STRICT_TYPES()) {
flags |= ZEND_PARSE_PARAMS_STRICT;
}
@@ -891,7 +891,7 @@ ZEND_API int zend_parse_method_parameters_ex(int flags, int num_args, zval *this
zval **object;
zend_class_entry *ce;
- if (EX_PREV_USES_STRICT_TYPES()) {
+ if (ZEND_ARG_USES_STRICT_TYPES()) {
flags |= ZEND_PARSE_PARAMS_STRICT;
}
diff --git a/Zend/zend_API.h b/Zend/zend_API.h
index e0f39e98a2..4da7002477 100644
--- a/Zend/zend_API.h
+++ b/Zend/zend_API.h
@@ -720,7 +720,7 @@ ZEND_API void zend_wrong_callback_error(int severity, int num, char *error, zend
#define ZPP_ERROR_WRONG_COUNT 5
#define ZEND_PARSE_PARAMETERS_START_EX(flags, min_num_args, max_num_args) do { \
- zend_bool _strict = EX_PREV_USES_STRICT_TYPES(); \
+ zend_bool _strict = ZEND_ARG_USES_STRICT_TYPES(); \
const int _flags = (flags) | (_strict ? ZEND_PARSE_PARAMS_STRICT : 0); \
int _min_num_args = (min_num_args); \
int _max_num_args = (max_num_args); \
diff --git a/Zend/zend_compile.h b/Zend/zend_compile.h
index cedd5d6808..c53833f149 100644
--- a/Zend/zend_compile.h
+++ b/Zend/zend_compile.h
@@ -462,9 +462,19 @@ struct _zend_execute_data {
#define EX_CALL_KIND() ZEND_CALL_KIND(execute_data)
#define EX_NUM_ARGS() ZEND_CALL_NUM_ARGS(execute_data)
-#define EX_USES_STRICT_TYPES() _EX_USES_STRICT_TYPES(EG(current_execute_data))
-#define EX_PREV_USES_STRICT_TYPES() _EX_USES_STRICT_TYPES(EG(current_execute_data)->prev_execute_data)
-#define _EX_USES_STRICT_TYPES(ex_data) ((ex_data) && (ex_data)->func && ZEND_USER_CODE((ex_data)->func->type) && ((ex_data)->func->op_array.fn_flags & ZEND_ACC_STRICT_TYPES) ? 1 : 0)
+#define ZEND_CALL_USES_STRICT_TYPES(call) \
+ (((call)->func->common.fn_flags & ZEND_ACC_STRICT_TYPES) != 0)
+
+#define EX_USES_STRICT_TYPES() \
+ ZEND_CALL_USES_STRICT_TYPES(execute_data)
+
+#define ZEND_ARG_USES_STRICT_TYPES() \
+ (EG(current_execute_data)->prev_execute_data && \
+ EG(current_execute_data)->prev_execute_data->func && \
+ ZEND_CALL_USES_STRICT_TYPES(EG(current_execute_data)->prev_execute_data))
+
+#define ZEND_RET_USES_STRICT_TYPES() \
+ ZEND_CALL_USES_STRICT_TYPES(EG(current_execute_data))
#define EX_VAR(n) ZEND_CALL_VAR(execute_data, n)
#define EX_VAR_NUM(n) ZEND_CALL_VAR_NUM(execute_data, n)
diff --git a/Zend/zend_execute.c b/Zend/zend_execute.c
index 699c1ca3de..b98d7cec47 100644
--- a/Zend/zend_execute.c
+++ b/Zend/zend_execute.c
@@ -651,8 +651,10 @@ static int is_null_constant(zval *default_value)
return 0;
}
-static zend_bool zend_verify_scalar_type_hint(zend_uchar type_hint, zval *arg, zend_bool strict)
+static zend_bool zend_verify_weak_scalar_type_hint(zend_uchar type_hint, zval *arg)
{
+ zend_bool strict = 0;
+
switch (type_hint) {
case _IS_BOOL: {
zend_bool dest;
@@ -698,24 +700,24 @@ static zend_bool zend_verify_scalar_type_hint(zend_uchar type_hint, zval *arg, z
}
}
-static inline int zend_verify_scalar_type_error(zend_uchar type_hint, zend_uchar allow_null, zval *arg, zval *default_value, zend_bool strict)
+static zend_bool zend_verify_scalar_type_hint(zend_uchar type_hint, zval *arg, zend_bool strict)
{
- if (UNEXPECTED(!ZEND_SAME_FAKE_TYPE(type_hint, Z_TYPE_P(arg)))) {
- if (Z_TYPE_P(arg) == IS_NULL) {
- if (!allow_null && (!default_value || !is_null_constant(default_value))) {
- return 1;
- }
- } else if (!zend_verify_scalar_type_hint(type_hint, arg, strict)) {
- return 1;
+ if (UNEXPECTED(strict)) {
+ /* SSTH Exception: IS_LONG ma be accepted instead as IS_DOUBLE */
+ if (type_hint != IS_DOUBLE || Z_TYPE_P(arg) != IS_LONG) {
+ return 0;
}
+ } else if (UNEXPECTED(Z_TYPE_P(arg) == IS_NULL)) {
+ /* FIXME: Is this exception on purpose ??? */
+ return 0;
}
- return 0;
+ return zend_verify_weak_scalar_type_hint(type_hint, arg);
}
-static void zend_verify_internal_arg_type(zend_function *zf, uint32_t arg_num, zval *arg, zend_bool strict)
+static void zend_verify_internal_arg_type(zend_function *zf, uint32_t arg_num, zval *arg)
{
zend_internal_arg_info *cur_arg_info;
- char *need_msg;
+ char *need_msg, *class_name;
zend_class_entry *ce;
if (EXPECTED(arg_num <= zf->internal_function.num_args)) {
@@ -726,39 +728,37 @@ static void zend_verify_internal_arg_type(zend_function *zf, uint32_t arg_num, z
return;
}
- if (cur_arg_info->class_name) {
- char *class_name;
-
+ if (cur_arg_info->type_hint) {
ZVAL_DEREF(arg);
- if (Z_TYPE_P(arg) == IS_OBJECT) {
- need_msg = zend_verify_internal_arg_class_kind((zend_internal_arg_info*)cur_arg_info, &class_name, &ce);
- if (!ce || !instanceof_function(Z_OBJCE_P(arg), ce)) {
- zend_verify_arg_error(zf, arg_num, need_msg, class_name, "instance of ", Z_OBJCE_P(arg)->name->val, arg);
+ if (EXPECTED(cur_arg_info->type_hint == Z_TYPE_P(arg))) {
+ if (cur_arg_info->class_name) {
+ need_msg = zend_verify_internal_arg_class_kind((zend_internal_arg_info*)cur_arg_info, &class_name, &ce);
+ if (!ce || !instanceof_function(Z_OBJCE_P(arg), ce)) {
+ zend_verify_arg_error(zf, arg_num, need_msg, class_name, "instance of ", Z_OBJCE_P(arg)->name->val, arg);
+ }
}
} else if (Z_TYPE_P(arg) != IS_NULL || !cur_arg_info->allow_null) {
- need_msg = zend_verify_internal_arg_class_kind((zend_internal_arg_info*)cur_arg_info, &class_name, &ce);
- zend_verify_arg_error(zf, arg_num, need_msg, class_name, zend_zval_type_name(arg), "", arg);
- }
- } else if (cur_arg_info->type_hint) {
- ZVAL_DEREF(arg);
- if (cur_arg_info->type_hint == IS_ARRAY) {
- if (Z_TYPE_P(arg) != IS_ARRAY && (Z_TYPE_P(arg) != IS_NULL || !cur_arg_info->allow_null)) {
- zend_verify_arg_error(zf, arg_num, "be of the type array", "", zend_zval_type_name(arg), "", arg);
- }
- } else if (cur_arg_info->type_hint == IS_CALLABLE) {
- if (!zend_is_callable(arg, IS_CALLABLE_CHECK_SILENT, NULL) && (Z_TYPE_P(arg) != IS_NULL || !cur_arg_info->allow_null)) {
- zend_verify_arg_error(zf, arg_num, "be callable", "", zend_zval_type_name(arg), "", arg);
+ if (cur_arg_info->class_name) {
+ need_msg = zend_verify_internal_arg_class_kind((zend_internal_arg_info*)cur_arg_info, &class_name, &ce);
+ zend_verify_arg_error(zf, arg_num, need_msg, class_name, zend_zval_type_name(arg), "", arg);
+ } else if (cur_arg_info->type_hint == IS_CALLABLE) {
+ if (!zend_is_callable(arg, IS_CALLABLE_CHECK_SILENT, NULL)) {
+ zend_verify_arg_error(zf, arg_num, "be callable", "", zend_zval_type_name(arg), "", arg);
+ }
+ } else if (cur_arg_info->type_hint == _IS_BOOL &&
+ EXPECTED(Z_TYPE_P(arg) == IS_FALSE || Z_TYPE_P(arg) == IS_TRUE)) {
+ /* pass */
+ } else if (UNEXPECTED(!zend_verify_scalar_type_hint(cur_arg_info->type_hint, arg, ZEND_CALL_USES_STRICT_TYPES(EG(current_execute_data))))) {
+ zend_verify_arg_error(zf, arg_num, "be of the type ", zend_get_type_by_const(cur_arg_info->type_hint), zend_zval_type_name(arg), "", arg);
}
- } else if (UNEXPECTED(zend_verify_scalar_type_error(cur_arg_info->type_hint, cur_arg_info->allow_null, arg, NULL, strict))) {
- zend_verify_arg_error(zf, arg_num, "be of the type ", zend_get_type_by_const(cur_arg_info->type_hint), zend_zval_type_name(arg), "", arg);
}
}
}
-static void zend_verify_arg_type(zend_function *zf, uint32_t arg_num, zval *arg, zval *default_value, zend_bool strict)
+static void zend_verify_arg_type(zend_function *zf, uint32_t arg_num, zval *arg, zval *default_value)
{
zend_arg_info *cur_arg_info;
- char *need_msg;
+ char *need_msg, *class_name;
zend_class_entry *ce;
if (EXPECTED(arg_num <= zf->common.num_args)) {
@@ -769,31 +769,29 @@ static void zend_verify_arg_type(zend_function *zf, uint32_t arg_num, zval *arg,
return;
}
- if (cur_arg_info->class_name) {
- char *class_name;
-
+ if (cur_arg_info->type_hint) {
ZVAL_DEREF(arg);
- if (Z_TYPE_P(arg) == IS_OBJECT) {
- need_msg = zend_verify_arg_class_kind(cur_arg_info, &class_name, &ce);
- if (!ce || !instanceof_function(Z_OBJCE_P(arg), ce)) {
- zend_verify_arg_error(zf, arg_num, need_msg, class_name, "instance of ", Z_OBJCE_P(arg)->name->val, arg);
+ if (EXPECTED(cur_arg_info->type_hint == Z_TYPE_P(arg))) {
+ if (cur_arg_info->class_name) {
+ need_msg = zend_verify_arg_class_kind(cur_arg_info, &class_name, &ce);
+ if (!ce || !instanceof_function(Z_OBJCE_P(arg), ce)) {
+ zend_verify_arg_error(zf, arg_num, need_msg, class_name, "instance of ", Z_OBJCE_P(arg)->name->val, arg);
+ }
}
} else if (Z_TYPE_P(arg) != IS_NULL || !(cur_arg_info->allow_null || (default_value && is_null_constant(default_value)))) {
- need_msg = zend_verify_arg_class_kind(cur_arg_info, &class_name, &ce);
- zend_verify_arg_error(zf, arg_num, need_msg, class_name, zend_zval_type_name(arg), "", arg);
- }
- } else if (cur_arg_info->type_hint) {
- ZVAL_DEREF(arg);
- if (cur_arg_info->type_hint == IS_ARRAY) {
- if (Z_TYPE_P(arg) != IS_ARRAY && (Z_TYPE_P(arg) != IS_NULL || !(cur_arg_info->allow_null || (default_value && is_null_constant(default_value))))) {
- zend_verify_arg_error(zf, arg_num, "be of the type array", "", zend_zval_type_name(arg), "", arg);
- }
- } else if (cur_arg_info->type_hint == IS_CALLABLE) {
- if (!zend_is_callable(arg, IS_CALLABLE_CHECK_SILENT, NULL) && (Z_TYPE_P(arg) != IS_NULL || !(cur_arg_info->allow_null || (default_value && is_null_constant(default_value))))) {
- zend_verify_arg_error(zf, arg_num, "be callable", "", zend_zval_type_name(arg), "", arg);
+ if (cur_arg_info->class_name) {
+ need_msg = zend_verify_arg_class_kind(cur_arg_info, &class_name, &ce);
+ zend_verify_arg_error(zf, arg_num, need_msg, class_name, zend_zval_type_name(arg), "", arg);
+ } else if (cur_arg_info->type_hint == IS_CALLABLE) {
+ if (!zend_is_callable(arg, IS_CALLABLE_CHECK_SILENT, NULL)) {
+ zend_verify_arg_error(zf, arg_num, "be callable", "", zend_zval_type_name(arg), "", arg);
+ }
+ } else if (cur_arg_info->type_hint == _IS_BOOL &&
+ EXPECTED(Z_TYPE_P(arg) == IS_FALSE || Z_TYPE_P(arg) == IS_TRUE)) {
+ /* pass */
+ } else if (UNEXPECTED(!zend_verify_scalar_type_hint(cur_arg_info->type_hint, arg, ZEND_ARG_USES_STRICT_TYPES()))) {
+ zend_verify_arg_error(zf, arg_num, "be of the type ", zend_get_type_by_const(cur_arg_info->type_hint), zend_zval_type_name(arg), "", arg);
}
- } else if (UNEXPECTED(zend_verify_scalar_type_error(cur_arg_info->type_hint, cur_arg_info->allow_null, arg, default_value, strict))) {
- zend_verify_arg_error(zf, arg_num, "be of the type ", zend_get_type_by_const(cur_arg_info->type_hint), zend_zval_type_name(arg), "", arg);
}
}
}
@@ -812,15 +810,13 @@ static inline int zend_verify_missing_arg_type(zend_function *zf, uint32_t arg_n
return 1;
}
- if (cur_arg_info->class_name) {
- char *class_name;
+ if (cur_arg_info->type_hint) {
+ if (cur_arg_info->class_name) {
+ char *class_name;
- need_msg = zend_verify_arg_class_kind(cur_arg_info, &class_name, &ce);
- zend_verify_arg_error(zf, arg_num, need_msg, class_name, "none", "", NULL);
- return 0;
- } else if (cur_arg_info->type_hint) {
- if (cur_arg_info->type_hint == IS_ARRAY) {
- zend_verify_arg_error(zf, arg_num, "be of the type array", "", "none", "", NULL);
+ need_msg = zend_verify_arg_class_kind(cur_arg_info, &class_name, &ce);
+ zend_verify_arg_error(zf, arg_num, need_msg, class_name, "none", "", NULL);
+ return 0;
} else if (cur_arg_info->type_hint == IS_CALLABLE) {
zend_verify_arg_error(zf, arg_num, "be callable", "", "none", "", NULL);
} else {
@@ -891,75 +887,73 @@ ZEND_API void zend_verify_internal_return_error(const zend_function *zf, const c
}
#if ZEND_DEBUG
-static int zend_verify_internal_return_type(zend_function *zf, zval *ret, zend_bool strict)
+static int zend_verify_internal_return_type(zend_function *zf, zval *ret)
{
zend_arg_info *ret_info = zf->common.arg_info - 1;
- char *need_msg;
+ char *need_msg, *class_name;
zend_class_entry *ce;
- if (ret_info->class_name) {
- char *class_name;
- if (Z_TYPE_P(ret) == IS_OBJECT) {
- need_msg = zend_verify_internal_arg_class_kind((zend_internal_arg_info *)ret_info, &class_name, &ce);
- if (!ce || !instanceof_function(Z_OBJCE_P(ret), ce)) {
- zend_verify_internal_return_error(zf, need_msg, class_name, "instance of ", Z_OBJCE_P(ret)->name->val);
- return 0;
+ if (ret_info->type_hint) {
+ if (EXPECTED(ret_info->type_hint == Z_TYPE_P(ret))) {
+ if (ret_info->class_name) {
+ need_msg = zend_verify_internal_arg_class_kind((zend_internal_arg_info *)ret_info, &class_name, &ce);
+ if (!ce || !instanceof_function(Z_OBJCE_P(ret), ce)) {
+ zend_verify_internal_return_error(zf, need_msg, class_name, "instance of ", Z_OBJCE_P(ret)->name->val);
+ return 0;
+ }
}
} else if (Z_TYPE_P(ret) != IS_NULL || !ret_info->allow_null) {
- need_msg = zend_verify_internal_arg_class_kind((zend_internal_arg_info *)ret_info, &class_name, &ce);
- zend_verify_internal_return_error(zf, need_msg, class_name, zend_zval_type_name(ret), "");
- return 0;
- }
- } else if (ret_info->type_hint) {
- if (ret_info->type_hint == IS_ARRAY) {
- if (Z_TYPE_P(ret) != IS_ARRAY && (Z_TYPE_P(ret) != IS_NULL || !ret_info->allow_null)) {
- zend_verify_internal_return_error(zf, "be of the type array", "", zend_zval_type_name(ret), "");
- return 0;
- }
- } else if (ret_info->type_hint == IS_CALLABLE) {
- if (!zend_is_callable(ret, IS_CALLABLE_CHECK_SILENT, NULL) && (Z_TYPE_P(ret) != IS_NULL || !ret_info->allow_null)) {
- zend_verify_internal_return_error(zf, "be callable", "", zend_zval_type_name(ret), "");
+ if (ret_info->class_name) {
+ need_msg = zend_verify_internal_arg_class_kind((zend_internal_arg_info *)ret_info, &class_name, &ce);
+ zend_verify_internal_return_error(zf, need_msg, class_name, zend_zval_type_name(ret), "");
+ } else if (ret_info->type_hint == IS_CALLABLE) {
+ if (!zend_is_callable(ret, IS_CALLABLE_CHECK_SILENT, NULL) && (Z_TYPE_P(ret) != IS_NULL || !ret_info->allow_null)) {
+ zend_verify_internal_return_error(zf, "be callable", "", zend_zval_type_name(ret), "");
+ return 0;
+ }
+ } else if (ret_info->type_hint == _IS_BOOL &&
+ EXPECTED(Z_TYPE_P(ret) == IS_FALSE || Z_TYPE_P(ret) == IS_TRUE)) {
+ /* pass */
+ } else {
+ /* Use strict check to verify return value of internal function */
+ zend_verify_internal_return_error(zf, "be of the type ", zend_get_type_by_const(ret_info->type_hint), zend_zval_type_name(ret), "");
return 0;
}
- } else if (UNEXPECTED(zend_verify_scalar_type_error(ret_info->type_hint, ret_info->allow_null, ret, NULL, strict))) {
- zend_verify_internal_return_error(zf, "be of the type ", zend_get_type_by_const(ret_info->type_hint), zend_zval_type_name(ret), "");
- return 0;
}
}
return 1;
}
#endif
-static void zend_verify_return_type(zend_function *zf, zval *ret, zend_bool strict)
+static void zend_verify_return_type(zend_function *zf, zval *ret)
{
zend_arg_info *ret_info = zf->common.arg_info - 1;
- char *need_msg;
+ char *need_msg, *class_name;
zend_class_entry *ce;
- if (ret_info->class_name) {
- char *class_name;
-
- if (Z_TYPE_P(ret) == IS_OBJECT) {
- need_msg = zend_verify_arg_class_kind(ret_info, &class_name, &ce);
- if (!ce || !instanceof_function(Z_OBJCE_P(ret), ce)) {
- zend_verify_return_error(zf, need_msg, class_name, "instance of ", Z_OBJCE_P(ret)->name->val);
+ if (ret_info->type_hint) {
+ if (EXPECTED(ret_info->type_hint == Z_TYPE_P(ret))) {
+ if (ret_info->class_name) {
+ need_msg = zend_verify_arg_class_kind(ret_info, &class_name, &ce);
+ if (!ce || !instanceof_function(Z_OBJCE_P(ret), ce)) {
+ zend_verify_return_error(zf, need_msg, class_name, "instance of ", Z_OBJCE_P(ret)->name->val);
+ }
}
} else if (Z_TYPE_P(ret) != IS_NULL || !ret_info->allow_null) {
- need_msg = zend_verify_arg_class_kind(ret_info, &class_name, &ce);
- zend_verify_return_error(zf, need_msg, class_name, zend_zval_type_name(ret), "");
- }
- } else if (ret_info->type_hint) {
- if (ret_info->type_hint == IS_ARRAY) {
- if (Z_TYPE_P(ret) != IS_ARRAY && (Z_TYPE_P(ret) != IS_NULL || !ret_info->allow_null)) {
- zend_verify_return_error(zf, "be of the type array", "", zend_zval_type_name(ret), "");
- }
- } else if (ret_info->type_hint == IS_CALLABLE) {
- if (!zend_is_callable(ret, IS_CALLABLE_CHECK_SILENT, NULL) && (Z_TYPE_P(ret) != IS_NULL || !ret_info->allow_null)) {
- zend_verify_return_error(zf, "be callable", "", zend_zval_type_name(ret), "");
+ if (ret_info->class_name) {
+ need_msg = zend_verify_arg_class_kind(ret_info, &class_name, &ce);
+ zend_verify_return_error(zf, need_msg, class_name, zend_zval_type_name(ret), "");
+ } else if (ret_info->type_hint == IS_CALLABLE) {
+ if (!zend_is_callable(ret, IS_CALLABLE_CHECK_SILENT, NULL)) {
+ zend_verify_return_error(zf, "be callable", "", zend_zval_type_name(ret), "");
+ }
+ } else if (ret_info->type_hint == _IS_BOOL &&
+ EXPECTED(Z_TYPE_P(ret) == IS_FALSE || Z_TYPE_P(ret) == IS_TRUE)) {
+ /* pass */
+ } else if (UNEXPECTED(!zend_verify_scalar_type_hint(ret_info->type_hint, ret, ZEND_RET_USES_STRICT_TYPES()))) {
+ zend_verify_return_error(zf, "be of the type ", zend_get_type_by_const(ret_info->type_hint), zend_zval_type_name(ret), "");
}
- } else if (UNEXPECTED(zend_verify_scalar_type_error(ret_info->type_hint, ret_info->allow_null, ret, NULL, strict))) {
- zend_verify_return_error(zf, "be of the type ", zend_get_type_by_const(ret_info->type_hint), zend_zval_type_name(ret), "");
}
}
}
@@ -970,15 +964,13 @@ static inline int zend_verify_missing_return_type(zend_function *zf)
char *need_msg;
zend_class_entry *ce;
- if (ret_info->class_name) {
- char *class_name;
+ if (ret_info->type_hint) {
+ if (ret_info->class_name) {
+ char *class_name;
- need_msg = zend_verify_arg_class_kind(ret_info, &class_name, &ce);
- zend_verify_return_error(zf, need_msg, class_name, "none", "");
- return 0;
- } else if (ret_info->type_hint) {
- if (ret_info->type_hint == IS_ARRAY) {
- zend_verify_return_error(zf, "be of the type array", "", "none", "");
+ need_msg = zend_verify_arg_class_kind(ret_info, &class_name, &ce);
+ zend_verify_return_error(zf, need_msg, class_name, "none", "");
+ return 0;
} else if (ret_info->type_hint == IS_CALLABLE) {
zend_verify_return_error(zf, "be callable", "", "none", "");
} else {
diff --git a/Zend/zend_vm_def.h b/Zend/zend_vm_def.h
index 2cc3588606..fd586e79cb 100644
--- a/Zend/zend_vm_def.h
+++ b/Zend/zend_vm_def.h
@@ -3232,7 +3232,7 @@ ZEND_VM_HANDLER(129, ZEND_DO_ICALL, ANY, ANY)
ZEND_ASSERT(
!call->func ||
!(call->func->common.fn_flags & ZEND_ACC_HAS_RETURN_TYPE) ||
- zend_verify_internal_return_type(call->func, EX_VAR(opline->result.var), EX_USES_STRICT_TYPES()));
+ zend_verify_internal_return_type(call->func, EX_VAR(opline->result.var)));
EG(current_execute_data) = call->prev_execute_data;
zend_vm_stack_free_args(call);
@@ -3339,7 +3339,7 @@ ZEND_VM_HANDLER(131, ZEND_DO_FCALL_BY_NAME, ANY, ANY)
zval *p = ZEND_CALL_ARG(call, 1);
for (i = 0; i < num_args; ++i) {
- zend_verify_internal_arg_type(fbc, i + 1, p, EX_USES_STRICT_TYPES());
+ zend_verify_internal_arg_type(fbc, i + 1, p);
p++;
}
if (UNEXPECTED(EG(exception) != NULL)) {
@@ -3360,7 +3360,7 @@ ZEND_VM_HANDLER(131, ZEND_DO_FCALL_BY_NAME, ANY, ANY)
ZEND_ASSERT(
!call->func ||
!(call->func->common.fn_flags & ZEND_ACC_HAS_RETURN_TYPE) ||
- zend_verify_internal_return_type(call->func, EX_VAR(opline->result.var), EX_USES_STRICT_TYPES()));
+ zend_verify_internal_return_type(call->func, EX_VAR(opline->result.var)));
EG(current_execute_data) = call->prev_execute_data;
zend_vm_stack_free_args(call);
@@ -3465,7 +3465,7 @@ ZEND_VM_HANDLER(60, ZEND_DO_FCALL, ANY, ANY)
zval *p = ZEND_CALL_ARG(call, 1);
for (i = 0; i < num_args; ++i) {
- zend_verify_internal_arg_type(fbc, i + 1, p, EX_USES_STRICT_TYPES());
+ zend_verify_internal_arg_type(fbc, i + 1, p);
if (UNEXPECTED(EG(exception) != NULL)) {
EG(current_execute_data) = call->prev_execute_data;
zend_vm_stack_free_args(call);
@@ -3497,7 +3497,7 @@ ZEND_VM_HANDLER(60, ZEND_DO_FCALL, ANY, ANY)
ZEND_ASSERT(
!call->func ||
!(call->func->common.fn_flags & ZEND_ACC_HAS_RETURN_TYPE) ||
- zend_verify_internal_return_type(call->func, EX_VAR(opline->result.var), EX_USES_STRICT_TYPES()));
+ zend_verify_internal_return_type(call->func, EX_VAR(opline->result.var)));
EG(current_execute_data) = call->prev_execute_data;
zend_vm_stack_free_args(call);
@@ -3615,7 +3615,7 @@ ZEND_VM_HANDLER(124, ZEND_VERIFY_RETURN_TYPE, CONST|TMP|VAR|UNUSED|CV, UNUSED)
}
}
- zend_verify_return_type(EX(func), retval_ptr, EX_USES_STRICT_TYPES());
+ zend_verify_return_type(EX(func), retval_ptr);
#endif
}
CHECK_EXCEPTION();
@@ -4387,7 +4387,7 @@ ZEND_VM_HANDLER(63, ZEND_RECV, ANY, ANY)
} else if (UNEXPECTED((EX(func)->op_array.fn_flags & ZEND_ACC_HAS_TYPE_HINTS) != 0)) {
zval *param = _get_zval_ptr_cv_undef_BP_VAR_W(execute_data, opline->result.var);
- zend_verify_arg_type(EX(func), arg_num, param, NULL, EX_PREV_USES_STRICT_TYPES());
+ zend_verify_arg_type(EX(func), arg_num, param, NULL);
CHECK_EXCEPTION();
}
@@ -4415,7 +4415,7 @@ ZEND_VM_HANDLER(64, ZEND_RECV_INIT, ANY, CONST)
}
if (UNEXPECTED((EX(func)->op_array.fn_flags & ZEND_ACC_HAS_TYPE_HINTS) != 0)) {
- zend_verify_arg_type(EX(func), arg_num, param, EX_CONSTANT(opline->op2), EX_PREV_USES_STRICT_TYPES());
+ zend_verify_arg_type(EX(func), arg_num, param, EX_CONSTANT(opline->op2));
}
CHECK_EXCEPTION();
@@ -4442,7 +4442,7 @@ ZEND_VM_HANDLER(164, ZEND_RECV_VARIADIC, ANY, ANY)
param = EX_VAR_NUM(EX(func)->op_array.last_var + EX(func)->op_array.T);
if (UNEXPECTED((EX(func)->op_array.fn_flags & ZEND_ACC_HAS_TYPE_HINTS) != 0)) {
do {
- zend_verify_arg_type(EX(func), arg_num, param, NULL, EX_USES_STRICT_TYPES());
+ zend_verify_arg_type(EX(func), arg_num, param, NULL);
if (Z_OPT_REFCOUNTED_P(param)) Z_ADDREF_P(param);
ZEND_HASH_FILL_ADD(param);
param++;
@@ -7268,35 +7268,42 @@ ZEND_VM_HANDLER(121, ZEND_STRLEN, CONST|TMPVAR|CV, ANY)
ZEND_VM_C_LABEL(try_strlen):
if (EXPECTED(Z_TYPE_P(value) == IS_STRING)) {
ZVAL_LONG(EX_VAR(opline->result.var), Z_STRLEN_P(value));
- } else if (EXPECTED(!EX_USES_STRICT_TYPES())) {
+ } else {
+ zend_bool strict;
+
if ((OP1_TYPE & (IS_VAR|IS_CV)) && Z_TYPE_P(value) == IS_REFERENCE) {
value = Z_REFVAL_P(value);
ZEND_VM_C_GOTO(try_strlen);
- } else if (Z_TYPE_P(value) < IS_TRUE) {
- ZVAL_LONG(EX_VAR(opline->result.var), 0);
- } else if (Z_TYPE_P(value) == IS_TRUE) {
- ZVAL_LONG(EX_VAR(opline->result.var), 1);
- } else if (Z_TYPE_P(value) <= IS_DOUBLE) {
- zend_string *str = zval_get_string(value);
- ZVAL_LONG(EX_VAR(opline->result.var), str->len);
- zend_string_release(str);
- } else if (Z_TYPE_P(value) == IS_OBJECT) {
- zend_string *str;
- zval tmp;
-
- ZVAL_COPY(&tmp, value);
- if (parse_arg_object_to_str(&tmp, &str, IS_STRING) == FAILURE) {
- ZEND_VM_C_GOTO(strlen_error);
- }
- ZVAL_LONG(EX_VAR(opline->result.var), str->len);
- zval_dtor(&tmp);
- } else {
-ZEND_VM_C_LABEL(strlen_error):
- zend_internal_type_error(0, "strlen() expects parameter 1 to be string, %s given", zend_get_type_by_const(Z_TYPE_P(value)));
- ZVAL_NULL(EX_VAR(opline->result.var));
}
- } else {
- zend_internal_type_error(1, "strlen() expects parameter 1 to be string, %s given", zend_get_type_by_const(Z_TYPE_P(value)));
+ strict = EX_USES_STRICT_TYPES();
+ do {
+ if (EXPECTED(!strict)) {
+ if (Z_TYPE_P(value) < IS_TRUE) {
+ ZVAL_LONG(EX_VAR(opline->result.var), 0);
+ break;
+ } else if (Z_TYPE_P(value) == IS_TRUE) {
+ ZVAL_LONG(EX_VAR(opline->result.var), 1);
+ break;
+ } else if (Z_TYPE_P(value) <= IS_DOUBLE) {
+ zend_string *str = zval_get_string(value);
+ ZVAL_LONG(EX_VAR(opline->result.var), str->len);
+ zend_string_release(str);
+ break;
+ } else if (Z_TYPE_P(value) == IS_OBJECT) {
+ zend_string *str;
+ zval tmp;
+
+ ZVAL_COPY(&tmp, value);
+ if (parse_arg_object_to_str(&tmp, &str, IS_STRING) == SUCCESS) {
+ ZVAL_LONG(EX_VAR(opline->result.var), str->len);
+ zval_dtor(&tmp);
+ break;
+ }
+ }
+ }
+ zend_internal_type_error(strict, "strlen() expects parameter 1 to be string, %s given", zend_get_type_by_const(Z_TYPE_P(value)));
+ ZVAL_NULL(EX_VAR(opline->result.var));
+ } while (0);
}
FREE_OP1();
CHECK_EXCEPTION();
diff --git a/Zend/zend_vm_execute.h b/Zend/zend_vm_execute.h
index 2ee2cf4d53..ebc21017ac 100644
--- a/Zend/zend_vm_execute.h
+++ b/Zend/zend_vm_execute.h
@@ -563,7 +563,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_DO_ICALL_SPEC_HANDLER(ZEND_OPC
ZEND_ASSERT(
!call->func ||
!(call->func->common.fn_flags & ZEND_ACC_HAS_RETURN_TYPE) ||
- zend_verify_internal_return_type(call->func, EX_VAR(opline->result.var), EX_USES_STRICT_TYPES()));
+ zend_verify_internal_return_type(call->func, EX_VAR(opline->result.var)));
EG(current_execute_data) = call->prev_execute_data;
zend_vm_stack_free_args(call);
@@ -670,7 +670,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_DO_FCALL_BY_NAME_SPEC_HANDLER(
zval *p = ZEND_CALL_ARG(call, 1);
for (i = 0; i < num_args; ++i) {
- zend_verify_internal_arg_type(fbc, i + 1, p, EX_USES_STRICT_TYPES());
+ zend_verify_internal_arg_type(fbc, i + 1, p);
p++;
}
if (UNEXPECTED(EG(exception) != NULL)) {
@@ -691,7 +691,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_DO_FCALL_BY_NAME_SPEC_HANDLER(
ZEND_ASSERT(
!call->func ||
!(call->func->common.fn_flags & ZEND_ACC_HAS_RETURN_TYPE) ||
- zend_verify_internal_return_type(call->func, EX_VAR(opline->result.var), EX_USES_STRICT_TYPES()));
+ zend_verify_internal_return_type(call->func, EX_VAR(opline->result.var)));
EG(current_execute_data) = call->prev_execute_data;
zend_vm_stack_free_args(call);
@@ -796,7 +796,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_DO_FCALL_SPEC_HANDLER(ZEND_OPC
zval *p = ZEND_CALL_ARG(call, 1);
for (i = 0; i < num_args; ++i) {
- zend_verify_internal_arg_type(fbc, i + 1, p, EX_USES_STRICT_TYPES());
+ zend_verify_internal_arg_type(fbc, i + 1, p);
if (UNEXPECTED(EG(exception) != NULL)) {
EG(current_execute_data) = call->prev_execute_data;
zend_vm_stack_free_args(call);
@@ -828,7 +828,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_DO_FCALL_SPEC_HANDLER(ZEND_OPC
ZEND_ASSERT(
!call->func ||
!(call->func->common.fn_flags & ZEND_ACC_HAS_RETURN_TYPE) ||
- zend_verify_internal_return_type(call->func, EX_VAR(opline->result.var), EX_USES_STRICT_TYPES()));
+ zend_verify_internal_return_type(call->func, EX_VAR(opline->result.var)));
EG(current_execute_data) = call->prev_execute_data;
zend_vm_stack_free_args(call);
@@ -1218,7 +1218,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_RECV_SPEC_HANDLER(ZEND_OPCODE_
} else if (UNEXPECTED((EX(func)->op_array.fn_flags & ZEND_ACC_HAS_TYPE_HINTS) != 0)) {
zval *param = _get_zval_ptr_cv_undef_BP_VAR_W(execute_data, opline->result.var);
- zend_verify_arg_type(EX(func), arg_num, param, NULL, EX_PREV_USES_STRICT_TYPES());
+ zend_verify_arg_type(EX(func), arg_num, param, NULL);
CHECK_EXCEPTION();
}
@@ -1245,7 +1245,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_RECV_VARIADIC_SPEC_HANDLER(ZEN
param = EX_VAR_NUM(EX(func)->op_array.last_var + EX(func)->op_array.T);
if (UNEXPECTED((EX(func)->op_array.fn_flags & ZEND_ACC_HAS_TYPE_HINTS) != 0)) {
do {
- zend_verify_arg_type(EX(func), arg_num, param, NULL, EX_USES_STRICT_TYPES());
+ zend_verify_arg_type(EX(func), arg_num, param, NULL);
if (Z_OPT_REFCOUNTED_P(param)) Z_ADDREF_P(param);
ZEND_HASH_FILL_ADD(param);
param++;
@@ -2078,7 +2078,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_RECV_INIT_SPEC_CONST_HANDLER(Z
}
if (UNEXPECTED((EX(func)->op_array.fn_flags & ZEND_ACC_HAS_TYPE_HINTS) != 0)) {
- zend_verify_arg_type(EX(func), arg_num, param, EX_CONSTANT(opline->op2), EX_PREV_USES_STRICT_TYPES());
+ zend_verify_arg_type(EX(func), arg_num, param, EX_CONSTANT(opline->op2));
}
CHECK_EXCEPTION();
@@ -3809,35 +3809,42 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_STRLEN_SPEC_CONST_HANDLER(ZEND
try_strlen:
if (EXPECTED(Z_TYPE_P(value) == IS_STRING)) {
ZVAL_LONG(EX_VAR(opline->result.var), Z_STRLEN_P(value));
- } else if (EXPECTED(!EX_USES_STRICT_TYPES())) {
+ } else {
+ zend_bool strict;
+
if ((IS_CONST & (IS_VAR|IS_CV)) && Z_TYPE_P(value) == IS_REFERENCE) {
value = Z_REFVAL_P(value);
goto try_strlen;
- } else if (Z_TYPE_P(value) < IS_TRUE) {
- ZVAL_LONG(EX_VAR(opline->result.var), 0);
- } else if (Z_TYPE_P(value) == IS_TRUE) {
- ZVAL_LONG(EX_VAR(opline->result.var), 1);
- } else if (Z_TYPE_P(value) <= IS_DOUBLE) {
- zend_string *str = zval_get_string(value);
- ZVAL_LONG(EX_VAR(opline->result.var), str->len);
- zend_string_release(str);
- } else if (Z_TYPE_P(value) == IS_OBJECT) {
- zend_string *str;
- zval tmp;
-
- ZVAL_COPY(&tmp, value);
- if (parse_arg_object_to_str(&tmp, &str, IS_STRING) == FAILURE) {
- goto strlen_error;
- }
- ZVAL_LONG(EX_VAR(opline->result.var), str->len);
- zval_dtor(&tmp);
- } else {
-strlen_error:
- zend_internal_type_error(0, "strlen() expects parameter 1 to be string, %s given", zend_get_type_by_const(Z_TYPE_P(value)));
- ZVAL_NULL(EX_VAR(opline->result.var));
}
- } else {
- zend_internal_type_error(1, "strlen() expects parameter 1 to be string, %s given", zend_get_type_by_const(Z_TYPE_P(value)));
+ strict = EX_USES_STRICT_TYPES();
+ do {
+ if (EXPECTED(!strict)) {
+ if (Z_TYPE_P(value) < IS_TRUE) {
+ ZVAL_LONG(EX_VAR(opline->result.var), 0);
+ break;
+ } else if (Z_TYPE_P(value) == IS_TRUE) {
+ ZVAL_LONG(EX_VAR(opline->result.var), 1);
+ break;
+ } else if (Z_TYPE_P(value) <= IS_DOUBLE) {
+ zend_string *str = zval_get_string(value);
+ ZVAL_LONG(EX_VAR(opline->result.var), str->len);
+ zend_string_release(str);
+ break;
+ } else if (Z_TYPE_P(value) == IS_OBJECT) {
+ zend_string *str;
+ zval tmp;
+
+ ZVAL_COPY(&tmp, value);
+ if (parse_arg_object_to_str(&tmp, &str, IS_STRING) == SUCCESS) {
+ ZVAL_LONG(EX_VAR(opline->result.var), str->len);
+ zval_dtor(&tmp);
+ break;
+ }
+ }
+ }
+ zend_internal_type_error(strict, "strlen() expects parameter 1 to be string, %s given", zend_get_type_by_const(Z_TYPE_P(value)));
+ ZVAL_NULL(EX_VAR(opline->result.var));
+ } while (0);
}
CHECK_EXCEPTION();
@@ -6988,7 +6995,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_VERIFY_RETURN_TYPE_SPEC_CONST_
}
}
- zend_verify_return_type(EX(func), retval_ptr, EX_USES_STRICT_TYPES());
+ zend_verify_return_type(EX(func), retval_ptr);
#endif
}
CHECK_EXCEPTION();
@@ -11949,7 +11956,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_VERIFY_RETURN_TYPE_SPEC_TMP_UN
}
}
- zend_verify_return_type(EX(func), retval_ptr, EX_USES_STRICT_TYPES());
+ zend_verify_return_type(EX(func), retval_ptr);
#endif
}
CHECK_EXCEPTION();
@@ -17310,7 +17317,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_VERIFY_RETURN_TYPE_SPEC_VAR_UN
}
}
- zend_verify_return_type(EX(func), retval_ptr, EX_USES_STRICT_TYPES());
+ zend_verify_return_type(EX(func), retval_ptr);
#endif
}
CHECK_EXCEPTION();
@@ -22928,7 +22935,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_VERIFY_RETURN_TYPE_SPEC_UNUSED
}
}
- zend_verify_return_type(EX(func), retval_ptr, EX_USES_STRICT_TYPES());
+ zend_verify_return_type(EX(func), retval_ptr);
#endif
}
CHECK_EXCEPTION();
@@ -27324,35 +27331,42 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_STRLEN_SPEC_CV_HANDLER(ZEND_OP
try_strlen:
if (EXPECTED(Z_TYPE_P(value) == IS_STRING)) {
ZVAL_LONG(EX_VAR(opline->result.var), Z_STRLEN_P(value));
- } else if (EXPECTED(!EX_USES_STRICT_TYPES())) {
+ } else {
+ zend_bool strict;
+
if ((IS_CV & (IS_VAR|IS_CV)) && Z_TYPE_P(value) == IS_REFERENCE) {
value = Z_REFVAL_P(value);
goto try_strlen;
- } else if (Z_TYPE_P(value) < IS_TRUE) {
- ZVAL_LONG(EX_VAR(opline->result.var), 0);
- } else if (Z_TYPE_P(value) == IS_TRUE) {
- ZVAL_LONG(EX_VAR(opline->result.var), 1);
- } else if (Z_TYPE_P(value) <= IS_DOUBLE) {
- zend_string *str = zval_get_string(value);
- ZVAL_LONG(EX_VAR(opline->result.var), str->len);
- zend_string_release(str);
- } else if (Z_TYPE_P(value) == IS_OBJECT) {
- zend_string *str;
- zval tmp;
-
- ZVAL_COPY(&tmp, value);
- if (parse_arg_object_to_str(&tmp, &str, IS_STRING) == FAILURE) {
- goto strlen_error;
- }
- ZVAL_LONG(EX_VAR(opline->result.var), str->len);
- zval_dtor(&tmp);
- } else {
-strlen_error:
- zend_internal_type_error(0, "strlen() expects parameter 1 to be string, %s given", zend_get_type_by_const(Z_TYPE_P(value)));
- ZVAL_NULL(EX_VAR(opline->result.var));
}
- } else {
- zend_internal_type_error(1, "strlen() expects parameter 1 to be string, %s given", zend_get_type_by_const(Z_TYPE_P(value)));
+ strict = EX_USES_STRICT_TYPES();
+ do {
+ if (EXPECTED(!strict)) {
+ if (Z_TYPE_P(value) < IS_TRUE) {
+ ZVAL_LONG(EX_VAR(opline->result.var), 0);
+ break;
+ } else if (Z_TYPE_P(value) == IS_TRUE) {
+ ZVAL_LONG(EX_VAR(opline->result.var), 1);
+ break;
+ } else if (Z_TYPE_P(value) <= IS_DOUBLE) {
+ zend_string *str = zval_get_string(value);
+ ZVAL_LONG(EX_VAR(opline->result.var), str->len);
+ zend_string_release(str);
+ break;
+ } else if (Z_TYPE_P(value) == IS_OBJECT) {
+ zend_string *str;
+ zval tmp;
+
+ ZVAL_COPY(&tmp, value);
+ if (parse_arg_object_to_str(&tmp, &str, IS_STRING) == SUCCESS) {
+ ZVAL_LONG(EX_VAR(opline->result.var), str->len);
+ zval_dtor(&tmp);
+ break;
+ }
+ }
+ }
+ zend_internal_type_error(strict, "strlen() expects parameter 1 to be string, %s given", zend_get_type_by_const(Z_TYPE_P(value)));
+ ZVAL_NULL(EX_VAR(opline->result.var));
+ } while (0);
}
CHECK_EXCEPTION();
@@ -31875,7 +31889,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_VERIFY_RETURN_TYPE_SPEC_CV_UNU
}
}
- zend_verify_return_type(EX(func), retval_ptr, EX_USES_STRICT_TYPES());
+ zend_verify_return_type(EX(func), retval_ptr);
#endif
}
CHECK_EXCEPTION();
@@ -37592,35 +37606,42 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_STRLEN_SPEC_TMPVAR_HANDLER(ZEN
try_strlen:
if (EXPECTED(Z_TYPE_P(value) == IS_STRING)) {
ZVAL_LONG(EX_VAR(opline->result.var), Z_STRLEN_P(value));
- } else if (EXPECTED(!EX_USES_STRICT_TYPES())) {
+ } else {
+ zend_bool strict;
+
if (((IS_TMP_VAR|IS_VAR) & (IS_VAR|IS_CV)) && Z_TYPE_P(value) == IS_REFERENCE) {
value = Z_REFVAL_P(value);
goto try_strlen;
- } else if (Z_TYPE_P(value) < IS_TRUE) {
- ZVAL_LONG(EX_VAR(opline->result.var), 0);
- } else if (Z_TYPE_P(value) == IS_TRUE) {
- ZVAL_LONG(EX_VAR(opline->result.var), 1);
- } else if (Z_TYPE_P(value) <= IS_DOUBLE) {
- zend_string *str = zval_get_string(value);
- ZVAL_LONG(EX_VAR(opline->result.var), str->len);
- zend_string_release(str);
- } else if (Z_TYPE_P(value) == IS_OBJECT) {
- zend_string *str;
- zval tmp;
-
- ZVAL_COPY(&tmp, value);
- if (parse_arg_object_to_str(&tmp, &str, IS_STRING) == FAILURE) {
- goto strlen_error;
- }
- ZVAL_LONG(EX_VAR(opline->result.var), str->len);
- zval_dtor(&tmp);
- } else {
-strlen_error:
- zend_internal_type_error(0, "strlen() expects parameter 1 to be string, %s given", zend_get_type_by_const(Z_TYPE_P(value)));
- ZVAL_NULL(EX_VAR(opline->result.var));
}
- } else {
- zend_internal_type_error(1, "strlen() expects parameter 1 to be string, %s given", zend_get_type_by_const(Z_TYPE_P(value)));
+ strict = EX_USES_STRICT_TYPES();
+ do {
+ if (EXPECTED(!strict)) {
+ if (Z_TYPE_P(value) < IS_TRUE) {
+ ZVAL_LONG(EX_VAR(opline->result.var), 0);
+ break;
+ } else if (Z_TYPE_P(value) == IS_TRUE) {
+ ZVAL_LONG(EX_VAR(opline->result.var), 1);
+ break;
+ } else if (Z_TYPE_P(value) <= IS_DOUBLE) {
+ zend_string *str = zval_get_string(value);
+ ZVAL_LONG(EX_VAR(opline->result.var), str->len);
+ zend_string_release(str);
+ break;
+ } else if (Z_TYPE_P(value) == IS_OBJECT) {
+ zend_string *str;
+ zval tmp;
+
+ ZVAL_COPY(&tmp, value);
+ if (parse_arg_object_to_str(&tmp, &str, IS_STRING) == SUCCESS) {
+ ZVAL_LONG(EX_VAR(opline->result.var), str->len);
+ zval_dtor(&tmp);
+ break;
+ }
+ }
+ }
+ zend_internal_type_error(strict, "strlen() expects parameter 1 to be string, %s given", zend_get_type_by_const(Z_TYPE_P(value)));
+ ZVAL_NULL(EX_VAR(opline->result.var));
+ } while (0);
}
zval_ptr_dtor_nogc(free_op1);
CHECK_EXCEPTION();