mirror of
https://github.com/php/php-src.git
synced 2026-04-27 18:23:26 +02:00
Fixed bug #37251 (deadlock when custom error handler is to catch array type hint error).
This commit is contained in:
@@ -0,0 +1,19 @@
|
||||
--TEST--
|
||||
Bug #37251 (deadlock when custom error handler is to catch array type hint error)
|
||||
--FILE--
|
||||
<?php
|
||||
function error_handler($errno, $errstr, $errfile, $errline, $context) {
|
||||
echo 'OK';
|
||||
}
|
||||
|
||||
set_error_handler('error_handler');
|
||||
|
||||
class Foo {
|
||||
function bar(array $foo) {
|
||||
}
|
||||
}
|
||||
|
||||
$foo = new Foo();
|
||||
$foo->bar();
|
||||
--EXPECT--
|
||||
OK
|
||||
+12
-7
@@ -470,7 +470,7 @@ static inline void make_real_object(zval **object_ptr TSRMLS_DC)
|
||||
}
|
||||
}
|
||||
|
||||
static inline void zend_verify_arg_type(zend_function *zf, zend_uint arg_num, zval *arg TSRMLS_DC)
|
||||
static inline int zend_verify_arg_type(zend_function *zf, zend_uint arg_num, zval *arg TSRMLS_DC)
|
||||
{
|
||||
zend_arg_info *cur_arg_info;
|
||||
zend_execute_data *ptr = EG(current_execute_data)->prev_execute_data;
|
||||
@@ -479,7 +479,7 @@ static inline void zend_verify_arg_type(zend_function *zf, zend_uint arg_num, zv
|
||||
|
||||
if (!zf->common.arg_info
|
||||
|| arg_num>zf->common.num_args) {
|
||||
return;
|
||||
return 1;
|
||||
}
|
||||
|
||||
cur_arg_info = &zf->common.arg_info[arg_num-1];
|
||||
@@ -494,6 +494,7 @@ static inline void zend_verify_arg_type(zend_function *zf, zend_uint arg_num, zv
|
||||
} else {
|
||||
zend_error(E_RECOVERABLE_ERROR, "Argument %d passed to %v%s%v() must be an object of class %v", arg_num, fclass, fsep, fname, cur_arg_info->class_name);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
switch (Z_TYPE_P(arg)) {
|
||||
case IS_NULL:
|
||||
@@ -503,14 +504,14 @@ static inline void zend_verify_arg_type(zend_function *zf, zend_uint arg_num, zv
|
||||
} else {
|
||||
zend_error(E_RECOVERABLE_ERROR, "Argument %d passed to %v%s%v() must not be null", arg_num, fclass, fsep, fname);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
break;
|
||||
case IS_OBJECT: {
|
||||
zend_class_entry *ce = zend_u_fetch_class(UG(unicode) ? IS_UNICODE : IS_STRING, cur_arg_info->class_name, cur_arg_info->class_name_len, ZEND_FETCH_CLASS_AUTO TSRMLS_CC);
|
||||
if (!instanceof_function(Z_OBJCE_P(arg), ce TSRMLS_CC)) {
|
||||
char *error_msg;
|
||||
|
||||
if (ce->ce_flags & ZEND_ACC_INTERFACE) {
|
||||
if (ce->ce_flags & ZEND_ACC_INTERFACE) {
|
||||
error_msg = "implement interface";
|
||||
} else {
|
||||
error_msg = "be an instance of";
|
||||
@@ -520,6 +521,7 @@ static inline void zend_verify_arg_type(zend_function *zf, zend_uint arg_num, zv
|
||||
} else {
|
||||
zend_error(E_RECOVERABLE_ERROR, "Argument %d passed to %v%s%v() must %s %v", arg_num, fclass, fsep, fname, error_msg, ce->name);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
break;
|
||||
@@ -529,15 +531,16 @@ static inline void zend_verify_arg_type(zend_function *zf, zend_uint arg_num, zv
|
||||
} else {
|
||||
zend_error(E_RECOVERABLE_ERROR, "Argument %d passed to %v%s%v() must be an object of class %v", arg_num, fclass, fsep, fname, cur_arg_info->class_name);
|
||||
}
|
||||
break;
|
||||
return 0;
|
||||
}
|
||||
} else if (cur_arg_info->array_type_hint) {
|
||||
} else if (cur_arg_info->array_type_hint) {
|
||||
if (!arg) {
|
||||
if (ptr && ptr->op_array) {
|
||||
zend_error(E_RECOVERABLE_ERROR, "Argument %d passed to %v%s%v() must be an array, called in %s on line %d and defined", arg_num, fclass, fsep, fname, ptr->op_array->filename, ptr->opline->lineno);
|
||||
} else {
|
||||
zend_error(E_RECOVERABLE_ERROR, "Argument %d passed to %v%s%v() must be an array", arg_num, fclass, fsep, fname);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
switch (Z_TYPE_P(arg)) {
|
||||
case IS_NULL:
|
||||
@@ -547,6 +550,7 @@ static inline void zend_verify_arg_type(zend_function *zf, zend_uint arg_num, zv
|
||||
} else {
|
||||
zend_error(E_RECOVERABLE_ERROR, "Argument %d passed to %v%s%v() must not be null", arg_num, fclass, fsep, fname);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
break;
|
||||
case IS_ARRAY:
|
||||
@@ -557,9 +561,10 @@ static inline void zend_verify_arg_type(zend_function *zf, zend_uint arg_num, zv
|
||||
} else {
|
||||
zend_error(E_RECOVERABLE_ERROR, "Argument %d passed to %v%s%v() must be an array", arg_num, fclass, fsep, fname);
|
||||
}
|
||||
break;
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
||||
|
||||
+6
-5
@@ -2286,11 +2286,12 @@ ZEND_VM_HANDLER(63, ZEND_RECV, ANY, ANY)
|
||||
zstr class_name = get_active_class_name(&space TSRMLS_CC);
|
||||
zend_execute_data *ptr = EX(prev_execute_data);
|
||||
|
||||
zend_verify_arg_type((zend_function *) EG(active_op_array), arg_num, NULL TSRMLS_CC);
|
||||
if(ptr && ptr->op_array) {
|
||||
zend_error(E_WARNING, "Missing argument %ld for %v%s%v(), called in %s on line %d and defined", Z_LVAL(opline->op1.u.constant), class_name, space, get_active_function_name(TSRMLS_C), ptr->op_array->filename, ptr->opline->lineno);
|
||||
} else {
|
||||
zend_error(E_WARNING, "Missing argument %ld for %v%s%v()", Z_LVAL(opline->op1.u.constant), class_name, space, get_active_function_name(TSRMLS_C));
|
||||
if (zend_verify_arg_type((zend_function *) EG(active_op_array), arg_num, NULL TSRMLS_CC)) {
|
||||
if(ptr && ptr->op_array) {
|
||||
zend_error(E_WARNING, "Missing argument %ld for %v%s%v(), called in %s on line %d and defined", Z_LVAL(opline->op1.u.constant), class_name, space, get_active_function_name(TSRMLS_C), ptr->op_array->filename, ptr->opline->lineno);
|
||||
} else {
|
||||
zend_error(E_WARNING, "Missing argument %ld for %v%s%v()", Z_LVAL(opline->op1.u.constant), class_name, space, get_active_function_name(TSRMLS_C));
|
||||
}
|
||||
}
|
||||
if (opline->result.op_type == IS_VAR) {
|
||||
PZVAL_UNLOCK_FREE(*EX_T(opline->result.u.var).var.ptr_ptr);
|
||||
|
||||
@@ -370,11 +370,12 @@ static int ZEND_RECV_SPEC_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
|
||||
zstr class_name = get_active_class_name(&space TSRMLS_CC);
|
||||
zend_execute_data *ptr = EX(prev_execute_data);
|
||||
|
||||
zend_verify_arg_type((zend_function *) EG(active_op_array), arg_num, NULL TSRMLS_CC);
|
||||
if(ptr && ptr->op_array) {
|
||||
zend_error(E_WARNING, "Missing argument %ld for %v%s%v(), called in %s on line %d and defined", Z_LVAL(opline->op1.u.constant), class_name, space, get_active_function_name(TSRMLS_C), ptr->op_array->filename, ptr->opline->lineno);
|
||||
} else {
|
||||
zend_error(E_WARNING, "Missing argument %ld for %v%s%v()", Z_LVAL(opline->op1.u.constant), class_name, space, get_active_function_name(TSRMLS_C));
|
||||
if (zend_verify_arg_type((zend_function *) EG(active_op_array), arg_num, NULL TSRMLS_CC)) {
|
||||
if(ptr && ptr->op_array) {
|
||||
zend_error(E_WARNING, "Missing argument %ld for %v%s%v(), called in %s on line %d and defined", Z_LVAL(opline->op1.u.constant), class_name, space, get_active_function_name(TSRMLS_C), ptr->op_array->filename, ptr->opline->lineno);
|
||||
} else {
|
||||
zend_error(E_WARNING, "Missing argument %ld for %v%s%v()", Z_LVAL(opline->op1.u.constant), class_name, space, get_active_function_name(TSRMLS_C));
|
||||
}
|
||||
}
|
||||
if (opline->result.op_type == IS_VAR) {
|
||||
PZVAL_UNLOCK_FREE(*EX_T(opline->result.u.var).var.ptr_ptr);
|
||||
|
||||
Reference in New Issue
Block a user