}
}
}
+
+ if (cur_arg_info->class_name || cur_arg_info->type_hint) {
+ CG(active_op_array)->fn_flags |= ZEND_ACC_HAS_TYPE_HINTS;
+ }
}
/* }}} */
return ret;
}
+static zend_always_inline zval *_get_zval_ptr_cv_undef_BP_VAR_W(const zend_execute_data *execute_data, zend_uint var TSRMLS_DC)
+{
+ return EX_VAR(var);
+}
+
static zend_always_inline zval *_get_zval_ptr_cv_deref_BP_VAR_W(const zend_execute_data *execute_data, zend_uint var TSRMLS_DC)
{
zval *ret = EX_VAR(var);
}
}
-ZEND_API int zend_verify_arg_error(int error_type, const zend_function *zf, zend_uint arg_num, const char *need_msg, const char *need_kind, const char *given_msg, const char *given_kind TSRMLS_DC)
+ZEND_API void zend_verify_arg_error(int error_type, const zend_function *zf, zend_uint arg_num, const char *need_msg, const char *need_kind, const char *given_msg, const char *given_kind TSRMLS_DC)
{
zend_execute_data *ptr = EG(current_execute_data)->prev_execute_data;
const char *fname = zf->common.function_name->val;
} else {
zend_error(error_type, "Argument %d passed to %s%s%s() must %s%s, %s%s given", arg_num, fclass, fsep, fname, need_msg, need_kind, given_msg, given_kind);
}
- return 0;
}
-static inline int zend_verify_arg_type(zend_function *zf, zend_uint arg_num, zval *arg, ulong fetch_type TSRMLS_DC)
+static void zend_verify_arg_type(zend_function *zf, zend_uint arg_num, zval *arg, ulong fetch_type TSRMLS_DC)
{
zend_arg_info *cur_arg_info;
char *need_msg;
zend_class_entry *ce;
- if (!zf->common.arg_info) {
- return 1;
+ if (UNEXPECTED(!zf->common.arg_info)) {
+ return;
}
- if (arg_num <= zf->common.num_args) {
+ if (EXPECTED(arg_num <= zf->common.num_args)) {
cur_arg_info = &zf->common.arg_info[arg_num-1];
} else if (zf->common.fn_flags & ZEND_ACC_VARIADIC) {
cur_arg_info = &zf->common.arg_info[zf->common.num_args-1];
} else {
- return 1;
+ return;
}
if (cur_arg_info->class_name) {
char *class_name;
- if (!arg) {
- need_msg = zend_verify_arg_class_kind(cur_arg_info, fetch_type, &class_name, &ce TSRMLS_CC);
- return zend_verify_arg_error(E_RECOVERABLE_ERROR, zf, arg_num, need_msg, class_name, "none", "" TSRMLS_CC);
- }
ZVAL_DEREF(arg);
if (Z_TYPE_P(arg) == IS_OBJECT) {
need_msg = zend_verify_arg_class_kind(cur_arg_info, fetch_type, &class_name, &ce TSRMLS_CC);
if (!ce || !instanceof_function(Z_OBJCE_P(arg), ce TSRMLS_CC)) {
- return zend_verify_arg_error(E_RECOVERABLE_ERROR, zf, arg_num, need_msg, class_name, "instance of ", Z_OBJCE_P(arg)->name->val TSRMLS_CC);
+ zend_verify_arg_error(E_RECOVERABLE_ERROR, zf, arg_num, need_msg, class_name, "instance of ", Z_OBJCE_P(arg)->name->val TSRMLS_CC);
}
} else if (Z_TYPE_P(arg) != IS_NULL || !cur_arg_info->allow_null) {
need_msg = zend_verify_arg_class_kind(cur_arg_info, fetch_type, &class_name, &ce TSRMLS_CC);
- return zend_verify_arg_error(E_RECOVERABLE_ERROR, zf, arg_num, need_msg, class_name, zend_zval_type_name(arg), "" TSRMLS_CC);
+ zend_verify_arg_error(E_RECOVERABLE_ERROR, zf, arg_num, need_msg, class_name, zend_zval_type_name(arg), "" TSRMLS_CC);
}
} else if (cur_arg_info->type_hint) {
switch(cur_arg_info->type_hint) {
case IS_ARRAY:
- if (!arg) {
- return zend_verify_arg_error(E_RECOVERABLE_ERROR, zf, arg_num, "be of the type array", "", "none", "" TSRMLS_CC);
- }
-
ZVAL_DEREF(arg);
if (Z_TYPE_P(arg) != IS_ARRAY && (Z_TYPE_P(arg) != IS_NULL || !cur_arg_info->allow_null)) {
- return zend_verify_arg_error(E_RECOVERABLE_ERROR, zf, arg_num, "be of the type array", "", zend_zval_type_name(arg), "" TSRMLS_CC);
+ zend_verify_arg_error(E_RECOVERABLE_ERROR, zf, arg_num, "be of the type array", "", zend_zval_type_name(arg), "" TSRMLS_CC);
}
break;
case IS_CALLABLE:
- if (!arg) {
- return zend_verify_arg_error(E_RECOVERABLE_ERROR, zf, arg_num, "be callable", "", "none", "" TSRMLS_CC);
- }
if (!zend_is_callable(arg, IS_CALLABLE_CHECK_SILENT, NULL TSRMLS_CC) && (Z_TYPE_P(arg) != IS_NULL || !cur_arg_info->allow_null)) {
- return zend_verify_arg_error(E_RECOVERABLE_ERROR, zf, arg_num, "be callable", "", zend_zval_type_name(arg), "" TSRMLS_CC);
+ zend_verify_arg_error(E_RECOVERABLE_ERROR, zf, arg_num, "be callable", "", zend_zval_type_name(arg), "" TSRMLS_CC);
}
break;
zend_error(E_ERROR, "Unknown typehint");
}
}
- return 1;
+}
+
+static inline int zend_verify_missing_arg_type(zend_function *zf, zend_uint arg_num, ulong fetch_type TSRMLS_DC)
+{
+ zend_arg_info *cur_arg_info;
+ char *need_msg;
+ zend_class_entry *ce;
+
+ if (UNEXPECTED(!zf->common.arg_info)) {
+ return 1;
+ }
+
+ if (EXPECTED(arg_num <= zf->common.num_args)) {
+ cur_arg_info = &zf->common.arg_info[arg_num-1];
+ } else if (zf->common.fn_flags & ZEND_ACC_VARIADIC) {
+ cur_arg_info = &zf->common.arg_info[zf->common.num_args-1];
+ } else {
+ return 1;
+ }
+
+ if (cur_arg_info->class_name) {
+ char *class_name;
+
+ need_msg = zend_verify_arg_class_kind(cur_arg_info, fetch_type, &class_name, &ce TSRMLS_CC);
+ zend_verify_arg_error(E_RECOVERABLE_ERROR, zf, arg_num, need_msg, class_name, "none", "" TSRMLS_CC);
+ } else if (cur_arg_info->type_hint) {
+ switch(cur_arg_info->type_hint) {
+ case IS_ARRAY:
+ zend_verify_arg_error(E_RECOVERABLE_ERROR, zf, arg_num, "be of the type array", "", "none", "" TSRMLS_CC);
+ break;
+
+ case IS_CALLABLE:
+ zend_verify_arg_error(E_RECOVERABLE_ERROR, zf, arg_num, "be callable", "", "none", "" TSRMLS_CC);
+ break;
+
+ default:
+ zend_error(E_ERROR, "Unknown typehint");
+ }
+ }
+ return 0;
+}
+
+static void zend_verify_missing_arg(zend_execute_data *execute_data, zend_uint arg_num TSRMLS_DC)
+{
+ if (EXPECTED(!(EX(op_array)->fn_flags & ZEND_ACC_HAS_TYPE_HINTS)) ||
+ zend_verify_missing_arg_type((zend_function *) EX(op_array), arg_num, EX(opline)->extended_value TSRMLS_CC)) {
+ const char *class_name = EX(op_array)->scope ? EX(op_array)->scope->name->val : "";
+ const char *space = EX(op_array)->scope ? "::" : "";
+ const char *func_name = EX(op_array)->function_name ? EX(op_array)->function_name->val : "main";
+ zend_execute_data *ptr = EX(prev_execute_data);
+
+ if(ptr && ptr->op_array) {
+ zend_error(E_WARNING, "Missing argument %u for %s%s%s(), called in %s on line %d and defined", arg_num, class_name, space, func_name, ptr->op_array->filename->val, ptr->opline->lineno);
+ } else {
+ zend_error(E_WARNING, "Missing argument %u for %s%s%s()", arg_num, class_name, space, func_name);
+ }
+ }
}
static inline void zend_assign_to_object(zval *retval, zval *object_ptr, zval *property_name, int value_type, znode_op *value_op, const zend_execute_data *execute_data, int opcode, const zend_literal *key TSRMLS_DC)
ZEND_API int zend_eval_stringl_ex(char *str, int str_len, zval *retval_ptr, char *string_name, int handle_exceptions TSRMLS_DC);
ZEND_API char * zend_verify_arg_class_kind(const zend_arg_info *cur_arg_info, ulong fetch_type, char **class_name, zend_class_entry **pce TSRMLS_DC);
-ZEND_API int zend_verify_arg_error(int error_type, const zend_function *zf, zend_uint arg_num, const char *need_msg, const char *need_kind, const char *given_msg, const char *given_kind TSRMLS_DC);
+ZEND_API void zend_verify_arg_error(int error_type, const zend_function *zf, zend_uint arg_num, const char *need_msg, const char *need_kind, const char *given_msg, const char *given_kind TSRMLS_DC);
static zend_always_inline void i_zval_ptr_dtor(zval *zval_ptr ZEND_FILE_LINE_DC TSRMLS_DC)
{
if (!Z_DELREF_P(zval_ptr)) {
ZEND_ASSERT(zval_ptr != &EG(uninitialized_zval));
_zval_dtor_func_for_ptr(Z_COUNTED_P(zval_ptr) ZEND_FILE_LINE_CC);
-//??? } else {
-//??? if (Z_REFCOUNT_P(zval_ptr) == 1 && Z_ISREF_P(zval_ptr)) {
- /* convert reference to regular value */
-//??? zend_reference *ref = Z_REF_P(zval_ptr);
-//??? ZVAL_COPY_VALUE(zval_ptr, &ref->val);
-//??? efree_rel(ref);
-//??? }
}
}
}
static zend_always_inline int zend_vm_stack_get_args_count_ex(zend_execute_data *ex)
{
- if (ex) {
- zval *p = ex->function_state.arguments;
- return Z_LVAL_P(p);
- } else {
- return 0;
- }
+ zval *p = ex->function_state.arguments;
+ return Z_LVAL_P(p);
}
static zend_always_inline zval* zend_vm_stack_get_arg_ex(zend_execute_data *ex, int requested_arg)
if (UNEXPECTED(requested_arg > arg_count)) {
return NULL;
}
- return (zval*)p - arg_count + requested_arg - 1;
+ return p - arg_count + requested_arg - 1;
}
static zend_always_inline int zend_vm_stack_get_args_count(TSRMLS_D)
{
- return zend_vm_stack_get_args_count_ex(EG(current_execute_data)->prev_execute_data);
+ if (EG(current_execute_data)->prev_execute_data) {
+ return zend_vm_stack_get_args_count_ex(EG(current_execute_data)->prev_execute_data);
+ } else {
+ return 0;
+ }
}
static zend_always_inline zval* zend_vm_stack_get_arg(int requested_arg TSRMLS_DC)
{
USE_OPLINE
zend_uint arg_num = opline->op1.num;
- zval *param = zend_vm_stack_get_arg_ex(EX(prev_execute_data), arg_num TSRMLS_CC);
+ zval *arguments = EX(prev_execute_data)->function_state.arguments;
+ zend_uint arg_count = Z_LVAL_P(arguments);
SAVE_OPLINE();
- if (UNEXPECTED(param == NULL)) {
- if (zend_verify_arg_type((zend_function *) EG(active_op_array), arg_num, NULL, opline->extended_value TSRMLS_CC)) {
- const char *space;
- const char *class_name;
- zend_execute_data *ptr;
-
- if (EG(active_op_array)->scope) {
- class_name = EG(active_op_array)->scope->name->val;
- space = "::";
- } else {
- class_name = space = "";
- }
- ptr = EX(prev_execute_data);
-
- if(ptr && ptr->op_array) {
- zend_error(E_WARNING, "Missing argument %u for %s%s%s(), called in %s on line %d and defined", opline->op1.num, class_name, space, get_active_function_name(TSRMLS_C), ptr->op_array->filename->val, ptr->opline->lineno);
- } else {
- zend_error(E_WARNING, "Missing argument %u for %s%s%s()", opline->op1.num, class_name, space, get_active_function_name(TSRMLS_C));
- }
- }
+ if (UNEXPECTED(arg_num > arg_count)) {
+ zend_verify_missing_arg(execute_data, arg_num TSRMLS_CC);
} else {
zval *var_ptr;
+ zval *param = arguments - arg_count + arg_num - 1;
- zend_verify_arg_type((zend_function *) EG(active_op_array), arg_num, param, opline->extended_value TSRMLS_CC);
- var_ptr = _get_zval_ptr_cv_BP_VAR_W(execute_data, opline->result.var TSRMLS_CC);
- if (Z_REFCOUNTED_P(var_ptr)) Z_DELREF_P(var_ptr);
+ if (UNEXPECTED((EX(op_array)->fn_flags & ZEND_ACC_HAS_TYPE_HINTS) != 0)) {
+ zend_verify_arg_type((zend_function *) EX(op_array), arg_num, param, opline->extended_value TSRMLS_CC);
+ }
+ var_ptr = _get_zval_ptr_cv_undef_BP_VAR_W(execute_data, opline->result.var TSRMLS_CC);
+ if (UNEXPECTED(Z_REFCOUNTED_P(var_ptr))) Z_DELREF_P(var_ptr);
ZVAL_COPY(var_ptr, param);
}
{
USE_OPLINE
zend_uint arg_num = opline->op1.num;
- zval *param = zend_vm_stack_get_arg_ex(EX(prev_execute_data), arg_num TSRMLS_CC);
+ zval *arguments = EX(prev_execute_data)->function_state.arguments;
+ zend_uint arg_count = Z_LVAL_P(arguments);
zval *var_ptr;
SAVE_OPLINE();
- var_ptr = _get_zval_ptr_cv_BP_VAR_W(execute_data, opline->result.var TSRMLS_CC);
- zval_ptr_dtor(var_ptr);
- if (param == NULL) {
+ var_ptr = _get_zval_ptr_cv_undef_BP_VAR_W(execute_data, opline->result.var TSRMLS_CC);
+ if (UNEXPECTED(Z_REFCOUNTED_P(var_ptr))) Z_DELREF_P(var_ptr);
+ if (arg_num > arg_count) {
ZVAL_COPY_VALUE(var_ptr, opline->op2.zv);
if (Z_OPT_CONSTANT_P(var_ptr)) {
zval_update_constant(var_ptr, 0 TSRMLS_CC);
}
}
} else {
+ zval *param = arguments - arg_count + arg_num - 1;
ZVAL_COPY(var_ptr, param);
}
- zend_verify_arg_type((zend_function *) EG(active_op_array), arg_num, var_ptr, opline->extended_value TSRMLS_CC);
+ if (UNEXPECTED((EX(op_array)->fn_flags & ZEND_ACC_HAS_TYPE_HINTS) != 0)) {
+ zend_verify_arg_type((zend_function *) EX(op_array), arg_num, var_ptr, opline->extended_value TSRMLS_CC);
+ }
CHECK_EXCEPTION();
ZEND_VM_NEXT_OPCODE();
{
USE_OPLINE
zend_uint arg_num = opline->op1.num;
- zend_uint arg_count = zend_vm_stack_get_args_count_ex(EX(prev_execute_data) TSRMLS_CC);
+ zval *arguments = EX(prev_execute_data)->function_state.arguments;
+ zend_uint arg_count = Z_LVAL_P(arguments);
zval *params;
SAVE_OPLINE();
- params = _get_zval_ptr_cv_BP_VAR_W(execute_data, opline->result.var TSRMLS_CC);
- if (Z_REFCOUNTED_P(params)) Z_DELREF_P(params);
+ params = _get_zval_ptr_cv_undef_BP_VAR_W(execute_data, opline->result.var TSRMLS_CC);
+ if (UNEXPECTED(Z_REFCOUNTED_P(params))) Z_DELREF_P(params);
if (arg_num <= arg_count) {
+ zval *param = arguments - arg_count + arg_num - 1;
array_init_size(params, arg_count - arg_num + 1);
+ if (UNEXPECTED((EX(op_array)->fn_flags & ZEND_ACC_HAS_TYPE_HINTS) != 0)) {
+ do {
+ zend_verify_arg_type((zend_function *) EX(op_array), arg_num, param, opline->extended_value TSRMLS_CC);
+ zend_hash_next_index_insert(Z_ARRVAL_P(params), param);
+ if (Z_REFCOUNTED_P(param)) Z_ADDREF_P(param);
+ param++;
+ } while (++arg_num <= arg_count);
+ } else {
+ do {
+ zend_hash_next_index_insert(Z_ARRVAL_P(params), param);
+ if (Z_REFCOUNTED_P(param)) Z_ADDREF_P(param);
+ param++;
+ } while (++arg_num <= arg_count);
+ }
} else {
array_init(params);
}
- for (; arg_num <= arg_count; ++arg_num) {
- zval *param = zend_vm_stack_get_arg_ex(EX(prev_execute_data), arg_num TSRMLS_CC);
- zend_verify_arg_type((zend_function *) EG(active_op_array), arg_num, param, opline->extended_value TSRMLS_CC);
- zend_hash_next_index_insert(Z_ARRVAL_P(params), param);
- if (Z_REFCOUNTED_P(param)) {
- Z_ADDREF_P(param);
- }
- }
-
CHECK_EXCEPTION();
ZEND_VM_NEXT_OPCODE();
}
{
USE_OPLINE
zend_uint arg_num = opline->op1.num;
- zval *param = zend_vm_stack_get_arg_ex(EX(prev_execute_data), arg_num TSRMLS_CC);
+ zval *arguments = EX(prev_execute_data)->function_state.arguments;
+ zend_uint arg_count = Z_LVAL_P(arguments);
SAVE_OPLINE();
- if (UNEXPECTED(param == NULL)) {
- if (zend_verify_arg_type((zend_function *) EG(active_op_array), arg_num, NULL, opline->extended_value TSRMLS_CC)) {
- const char *space;
- const char *class_name;
- zend_execute_data *ptr;
-
- if (EG(active_op_array)->scope) {
- class_name = EG(active_op_array)->scope->name->val;
- space = "::";
- } else {
- class_name = space = "";
- }
- ptr = EX(prev_execute_data);
-
- if(ptr && ptr->op_array) {
- zend_error(E_WARNING, "Missing argument %u for %s%s%s(), called in %s on line %d and defined", opline->op1.num, class_name, space, get_active_function_name(TSRMLS_C), ptr->op_array->filename->val, ptr->opline->lineno);
- } else {
- zend_error(E_WARNING, "Missing argument %u for %s%s%s()", opline->op1.num, class_name, space, get_active_function_name(TSRMLS_C));
- }
- }
+ if (UNEXPECTED(arg_num > arg_count)) {
+ zend_verify_missing_arg(execute_data, arg_num TSRMLS_CC);
} else {
zval *var_ptr;
+ zval *param = arguments - arg_count + arg_num - 1;
- zend_verify_arg_type((zend_function *) EG(active_op_array), arg_num, param, opline->extended_value TSRMLS_CC);
- var_ptr = _get_zval_ptr_cv_BP_VAR_W(execute_data, opline->result.var TSRMLS_CC);
- if (Z_REFCOUNTED_P(var_ptr)) Z_DELREF_P(var_ptr);
+ if (UNEXPECTED((EX(op_array)->fn_flags & ZEND_ACC_HAS_TYPE_HINTS) != 0)) {
+ zend_verify_arg_type((zend_function *) EX(op_array), arg_num, param, opline->extended_value TSRMLS_CC);
+ }
+ var_ptr = _get_zval_ptr_cv_undef_BP_VAR_W(execute_data, opline->result.var TSRMLS_CC);
+ if (UNEXPECTED(Z_REFCOUNTED_P(var_ptr))) Z_DELREF_P(var_ptr);
ZVAL_COPY(var_ptr, param);
}
{
USE_OPLINE
zend_uint arg_num = opline->op1.num;
- zend_uint arg_count = zend_vm_stack_get_args_count_ex(EX(prev_execute_data) TSRMLS_CC);
+ zval *arguments = EX(prev_execute_data)->function_state.arguments;
+ zend_uint arg_count = Z_LVAL_P(arguments);
zval *params;
SAVE_OPLINE();
- params = _get_zval_ptr_cv_BP_VAR_W(execute_data, opline->result.var TSRMLS_CC);
- if (Z_REFCOUNTED_P(params)) Z_DELREF_P(params);
+ params = _get_zval_ptr_cv_undef_BP_VAR_W(execute_data, opline->result.var TSRMLS_CC);
+ if (UNEXPECTED(Z_REFCOUNTED_P(params))) Z_DELREF_P(params);
if (arg_num <= arg_count) {
+ zval *param = arguments - arg_count + arg_num - 1;
array_init_size(params, arg_count - arg_num + 1);
+ if (UNEXPECTED((EX(op_array)->fn_flags & ZEND_ACC_HAS_TYPE_HINTS) != 0)) {
+ do {
+ zend_verify_arg_type((zend_function *) EX(op_array), arg_num, param, opline->extended_value TSRMLS_CC);
+ zend_hash_next_index_insert(Z_ARRVAL_P(params), param);
+ if (Z_REFCOUNTED_P(param)) Z_ADDREF_P(param);
+ param++;
+ } while (++arg_num <= arg_count);
+ } else {
+ do {
+ zend_hash_next_index_insert(Z_ARRVAL_P(params), param);
+ if (Z_REFCOUNTED_P(param)) Z_ADDREF_P(param);
+ param++;
+ } while (++arg_num <= arg_count);
+ }
} else {
array_init(params);
}
- for (; arg_num <= arg_count; ++arg_num) {
- zval *param = zend_vm_stack_get_arg_ex(EX(prev_execute_data), arg_num TSRMLS_CC);
- zend_verify_arg_type((zend_function *) EG(active_op_array), arg_num, param, opline->extended_value TSRMLS_CC);
- zend_hash_next_index_insert(Z_ARRVAL_P(params), param);
- if (Z_REFCOUNTED_P(param)) {
- Z_ADDREF_P(param);
- }
- }
-
CHECK_EXCEPTION();
ZEND_VM_NEXT_OPCODE();
}
{
USE_OPLINE
zend_uint arg_num = opline->op1.num;
- zval *param = zend_vm_stack_get_arg_ex(EX(prev_execute_data), arg_num TSRMLS_CC);
+ zval *arguments = EX(prev_execute_data)->function_state.arguments;
+ zend_uint arg_count = Z_LVAL_P(arguments);
zval *var_ptr;
SAVE_OPLINE();
- var_ptr = _get_zval_ptr_cv_BP_VAR_W(execute_data, opline->result.var TSRMLS_CC);
- zval_ptr_dtor(var_ptr);
- if (param == NULL) {
+ var_ptr = _get_zval_ptr_cv_undef_BP_VAR_W(execute_data, opline->result.var TSRMLS_CC);
+ if (UNEXPECTED(Z_REFCOUNTED_P(var_ptr))) Z_DELREF_P(var_ptr);
+ if (arg_num > arg_count) {
ZVAL_COPY_VALUE(var_ptr, opline->op2.zv);
if (Z_OPT_CONSTANT_P(var_ptr)) {
zval_update_constant(var_ptr, 0 TSRMLS_CC);
}
}
} else {
+ zval *param = arguments - arg_count + arg_num - 1;
ZVAL_COPY(var_ptr, param);
}
- zend_verify_arg_type((zend_function *) EG(active_op_array), arg_num, var_ptr, opline->extended_value TSRMLS_CC);
+ if (UNEXPECTED((EX(op_array)->fn_flags & ZEND_ACC_HAS_TYPE_HINTS) != 0)) {
+ zend_verify_arg_type((zend_function *) EX(op_array), arg_num, var_ptr, opline->extended_value TSRMLS_CC);
+ }
CHECK_EXCEPTION();
ZEND_VM_NEXT_OPCODE();