From: Dmitry Stogov Date: Fri, 5 May 2006 08:04:55 +0000 (+0000) Subject: Fixed bug #37251 (deadlock when custom error handler is to catch array type hint... X-Git-Tag: BEFORE_NEW_OUTPUT_API~300 X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=30ff22ca47d6fd73bc60820a685248f647de5a2d;p=php Fixed bug #37251 (deadlock when custom error handler is to catch array type hint error). --- diff --git a/Zend/tests/bug37251.phpt b/Zend/tests/bug37251.phpt new file mode 100644 index 0000000000..320d544ce5 --- /dev/null +++ b/Zend/tests/bug37251.phpt @@ -0,0 +1,19 @@ +--TEST-- +Bug #37251 (deadlock when custom error handler is to catch array type hint error) +--FILE-- +bar(); +--EXPECT-- +OK diff --git a/Zend/zend_execute.c b/Zend/zend_execute.c index 2f7ab9553c..0173573b23 100644 --- a/Zend/zend_execute.c +++ b/Zend/zend_execute.c @@ -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; } diff --git a/Zend/zend_vm_def.h b/Zend/zend_vm_def.h index 808c0cb9d0..0f19daffed 100644 --- a/Zend/zend_vm_def.h +++ b/Zend/zend_vm_def.h @@ -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); diff --git a/Zend/zend_vm_execute.h b/Zend/zend_vm_execute.h index a08f576afe..201c8e5075 100644 --- a/Zend/zend_vm_execute.h +++ b/Zend/zend_vm_execute.h @@ -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);