static inline void zend_assign_to_variable_reference(zval *variable_ptr, zval *value_ptr)
{
+ if (EXPECTED(!Z_ISREF_P(value_ptr))) {
+ ZVAL_NEW_REF(value_ptr, value_ptr);
+ }
if (EXPECTED(variable_ptr != value_ptr)) {
zend_reference *ref;
- ZVAL_MAKE_REF(value_ptr);
- Z_ADDREF_P(value_ptr);
- ref = Z_REF_P(value_ptr);
+ ref = Z_REF_P(value_ptr);
+ GC_REFCOUNT(ref)++;
zval_ptr_dtor(variable_ptr);
ZVAL_REF(variable_ptr, ref);
- } else {
- ZVAL_MAKE_REF(variable_ptr);
}
}
}
}
-static void zend_verify_arg_type(zend_function *zf, uint32_t arg_num, zval *arg, zval *default_value)
+static int 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, *class_name;
} else if (zf->common.fn_flags & ZEND_ACC_VARIADIC) {
cur_arg_info = &zf->common.arg_info[zf->common.num_args];
} else {
- return;
+ return 1;
}
if (cur_arg_info->type_hint) {
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);
+ return 0;
}
}
} else if (Z_TYPE_P(arg) != IS_NULL || !(cur_arg_info->allow_null || (default_value && is_null_constant(default_value)))) {
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);
+ return 0;
} 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);
+ return 0;
}
} 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);
+ return 0;
}
}
}
+ return 1;
}
static inline int zend_verify_missing_arg_type(zend_function *zf, uint32_t arg_num)
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 {
return 1;
}
-static void zend_verify_missing_arg(zend_execute_data *execute_data, uint32_t arg_num)
+static int zend_verify_missing_arg(zend_execute_data *execute_data, uint32_t arg_num)
{
if (EXPECTED(!(EX(func)->common.fn_flags & ZEND_ACC_HAS_TYPE_HINTS)) ||
zend_verify_missing_arg_type(EX(func), arg_num)) {
} else {
zend_error(E_WARNING, "Missing argument %u for %s%s%s()", arg_num, class_name, space, func_name);
}
+ return 1;
}
+ return 0;
}
ZEND_API void zend_verify_return_error(const zend_function *zf, const char *need_msg, const char *need_kind, const char *returned_msg, const char *returned_kind)
if (UNEXPECTED(arg_num > EX_NUM_ARGS())) {
SAVE_OPLINE();
- zend_verify_missing_arg(execute_data, arg_num);
- CHECK_EXCEPTION();
+ if (UNEXPECTED(!zend_verify_missing_arg(execute_data, arg_num))) {
+ HANDLE_EXCEPTION();
+ }
} 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);
SAVE_OPLINE();
- zend_verify_arg_type(EX(func), arg_num, param, NULL);
- CHECK_EXCEPTION();
+ if (UNEXPECTED(!zend_verify_arg_type(EX(func), arg_num, param, NULL))) {
+ HANDLE_EXCEPTION();
+ }
}
ZEND_VM_NEXT_OPCODE();
uint32_t arg_num = opline->op1.num;
zval *param;
- SAVE_OPLINE();
param = _get_zval_ptr_cv_undef_BP_VAR_W(execute_data, opline->result.var);
if (arg_num > EX_NUM_ARGS()) {
ZVAL_COPY_VALUE(param, EX_CONSTANT(opline->op2));
if (Z_OPT_CONSTANT_P(param)) {
+ SAVE_OPLINE();
if (UNEXPECTED(zval_update_constant_ex(param, 0, NULL) != SUCCESS)) {
ZVAL_UNDEF(param);
HANDLE_EXCEPTION();
}
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));
+ SAVE_OPLINE();
+ if (UNEXPECTED(!zend_verify_arg_type(EX(func), arg_num, param, EX_CONSTANT(opline->op2)))) {
+ HANDLE_EXCEPTION();
+ }
}
- CHECK_EXCEPTION();
ZEND_VM_NEXT_OPCODE();
}
zval *variable_ptr;
uint32_t idx;
- SAVE_OPLINE();
varname = GET_OP2_ZVAL_PTR(BP_VAR_R);
/* We store "hash slot index" + 1 (NULL is a mark of uninitialized cache slot) */
}
variable_ptr = GET_OP1_ZVAL_PTR_PTR_UNDEF(BP_VAR_W);
- zend_assign_to_variable_reference(variable_ptr, value);
- CHECK_EXCEPTION();
+ if (UNEXPECTED(!Z_ISREF_P(value))) {
+ ZVAL_NEW_REF(value, value);
+ }
+ if (EXPECTED(variable_ptr != value)) {
+ zend_reference *ref;
+
+ ref = Z_REF_P(value);
+ GC_REFCOUNT(ref)++;
+ if (UNEXPECTED(Z_REFCOUNTED_P(variable_ptr))) {
+ if (!Z_DELREF_P(variable_ptr)) {
+ SAVE_OPLINE();
+ zval_dtor_func_for_ptr(Z_COUNTED_P(variable_ptr));
+ if (UNEXPECTED(EG(exception))) {
+ ZVAL_NULL(variable_ptr);
+ HANDLE_EXCEPTION();
+ }
+ } else {
+ GC_ZVAL_CHECK_POSSIBLE_ROOT(variable_ptr);
+ }
+ }
+ ZVAL_REF(variable_ptr, ref);
+ }
+
ZEND_VM_NEXT_OPCODE();
}
if (UNEXPECTED(arg_num > EX_NUM_ARGS())) {
SAVE_OPLINE();
- zend_verify_missing_arg(execute_data, arg_num);
- CHECK_EXCEPTION();
+ if (UNEXPECTED(!zend_verify_missing_arg(execute_data, arg_num))) {
+ HANDLE_EXCEPTION();
+ }
} 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);
SAVE_OPLINE();
- zend_verify_arg_type(EX(func), arg_num, param, NULL);
- CHECK_EXCEPTION();
+ if (UNEXPECTED(!zend_verify_arg_type(EX(func), arg_num, param, NULL))) {
+ HANDLE_EXCEPTION();
+ }
}
ZEND_VM_NEXT_OPCODE();
uint32_t arg_num = opline->op1.num;
zval *param;
- SAVE_OPLINE();
param = _get_zval_ptr_cv_undef_BP_VAR_W(execute_data, opline->result.var);
if (arg_num > EX_NUM_ARGS()) {
ZVAL_COPY_VALUE(param, EX_CONSTANT(opline->op2));
if (Z_OPT_CONSTANT_P(param)) {
+ SAVE_OPLINE();
if (UNEXPECTED(zval_update_constant_ex(param, 0, NULL) != SUCCESS)) {
ZVAL_UNDEF(param);
HANDLE_EXCEPTION();
}
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));
+ SAVE_OPLINE();
+ if (UNEXPECTED(!zend_verify_arg_type(EX(func), arg_num, param, EX_CONSTANT(opline->op2)))) {
+ HANDLE_EXCEPTION();
+ }
}
- CHECK_EXCEPTION();
ZEND_VM_NEXT_OPCODE();
}
zval *variable_ptr;
uint32_t idx;
- SAVE_OPLINE();
varname = EX_CONSTANT(opline->op2);
/* We store "hash slot index" + 1 (NULL is a mark of uninitialized cache slot) */
}
variable_ptr = _get_zval_ptr_cv_undef_BP_VAR_W(execute_data, opline->op1.var);
- zend_assign_to_variable_reference(variable_ptr, value);
- CHECK_EXCEPTION();
+ if (UNEXPECTED(!Z_ISREF_P(value))) {
+ ZVAL_NEW_REF(value, value);
+ }
+ if (EXPECTED(variable_ptr != value)) {
+ zend_reference *ref;
+
+ ref = Z_REF_P(value);
+ GC_REFCOUNT(ref)++;
+ if (UNEXPECTED(Z_REFCOUNTED_P(variable_ptr))) {
+ if (!Z_DELREF_P(variable_ptr)) {
+ SAVE_OPLINE();
+ zval_dtor_func_for_ptr(Z_COUNTED_P(variable_ptr));
+ if (UNEXPECTED(EG(exception))) {
+ ZVAL_NULL(variable_ptr);
+ HANDLE_EXCEPTION();
+ }
+ } else {
+ GC_ZVAL_CHECK_POSSIBLE_ROOT(variable_ptr);
+ }
+ }
+ ZVAL_REF(variable_ptr, ref);
+ }
+
ZEND_VM_NEXT_OPCODE();
}