From 0529eeb4a6d9b826075d267d98c7bbee2ffd75ab Mon Sep 17 00:00:00 2001 From: Anthony Ferrara Date: Wed, 18 Mar 2015 15:22:21 -0400 Subject: [PATCH] Fix executor issue with ignoring strict types, which cleans up a bunch of errors. Additionally fix the expected error of 2 unrelated tests that was caused by a change to the core error messages --- Zend/tests/return_types/rfc002.phpt | 6 +-- .../explicit_weak_include_strict.phpt | 2 +- Zend/tests/typehints/strict_call_weak.phpt | 2 +- .../typehints/strict_call_weak_explicit.phpt | 2 +- Zend/tests/typehints/weak_include_strict.phpt | 2 +- .../variadic/typehint_suppressed_error.phpt | 2 +- Zend/zend.c | 2 +- Zend/zend_execute.c | 39 +++++++++++++++---- Zend/zend_execute.h | 1 + Zend/zend_vm_def.h | 6 +++ Zend/zend_vm_execute.h | 6 +++ tests/lang/catchable_error_002.phpt | 2 +- 12 files changed, 54 insertions(+), 18 deletions(-) diff --git a/Zend/tests/return_types/rfc002.phpt b/Zend/tests/return_types/rfc002.phpt index 7ccef60d3d..2f3ff02b1c 100644 --- a/Zend/tests/return_types/rfc002.phpt +++ b/Zend/tests/return_types/rfc002.phpt @@ -1,5 +1,5 @@ --TEST-- -RFC example: expected class int and returned integer +RFC example: Scalar Types --FILE-- --EXPECTF-- -Catchable fatal error: Argument 1 passed to takes_int() must be of the type integer, float given, called in %sweak_include_strict_2.inc on line 9 and defined in %sweak_include_strict_2.inc on line 5 +Fatal error: Argument 1 passed to takes_int() must be of the type integer, float given, called in %sweak_include_strict_2.inc on line 9 and defined in %sweak_include_strict_2.inc on line 5 diff --git a/Zend/tests/typehints/strict_call_weak.phpt b/Zend/tests/typehints/strict_call_weak.phpt index 45b87b042a..94d5953f2b 100644 --- a/Zend/tests/typehints/strict_call_weak.phpt +++ b/Zend/tests/typehints/strict_call_weak.phpt @@ -13,5 +13,5 @@ require 'strict_call_weak_2.inc'; function_declared_in_weak_mode(1.0); ?> --EXPECTF-- -Catchable fatal error: Argument 1 passed to function_declared_in_weak_mode() must be of the type integer, float given, called in %sstrict_call_weak.php on line 10 and defined in %sstrict_call_weak_2.inc on line 5 +Fatal error: Argument 1 passed to function_declared_in_weak_mode() must be of the type integer, float given, called in %sstrict_call_weak.php on line 10 and defined in %sstrict_call_weak_2.inc on line 5 diff --git a/Zend/tests/typehints/strict_call_weak_explicit.phpt b/Zend/tests/typehints/strict_call_weak_explicit.phpt index 07a311b06c..2d573e85f2 100644 --- a/Zend/tests/typehints/strict_call_weak_explicit.phpt +++ b/Zend/tests/typehints/strict_call_weak_explicit.phpt @@ -13,5 +13,5 @@ require 'strict_call_weak_explicit_2.inc'; function_declared_in_weak_mode(1.0); ?> --EXPECTF-- -Catchable fatal error: Argument 1 passed to function_declared_in_weak_mode() must be of the type integer, float given, called in %sstrict_call_weak_explicit.php on line 10 and defined in %sstrict_call_weak_explicit_2.inc on line 5 +Fatal error: Argument 1 passed to function_declared_in_weak_mode() must be of the type integer, float given, called in %sstrict_call_weak_explicit.php on line 10 and defined in %sstrict_call_weak_explicit_2.inc on line 5 diff --git a/Zend/tests/typehints/weak_include_strict.phpt b/Zend/tests/typehints/weak_include_strict.phpt index 371b26dd8b..c3a0820657 100644 --- a/Zend/tests/typehints/weak_include_strict.phpt +++ b/Zend/tests/typehints/weak_include_strict.phpt @@ -11,4 +11,4 @@ require 'weak_include_strict_2.inc'; // calls within that file should stay strict, despite being included by weak file ?> --EXPECTF-- -Catchable fatal error: Argument 1 passed to takes_int() must be of the type integer, float given, called in %sweak_include_strict_2.inc on line 9 and defined in %sweak_include_strict_2.inc on line 5 +Fatal error: Argument 1 passed to takes_int() must be of the type integer, float given, called in %sweak_include_strict_2.inc on line 9 and defined in %sweak_include_strict_2.inc on line 5 diff --git a/Zend/tests/variadic/typehint_suppressed_error.phpt b/Zend/tests/variadic/typehint_suppressed_error.phpt index f03ec43d0a..f72de5c69e 100644 --- a/Zend/tests/variadic/typehint_suppressed_error.phpt +++ b/Zend/tests/variadic/typehint_suppressed_error.phpt @@ -15,4 +15,4 @@ try { ?> --EXPECTF-- -string(%d) "Argument 3 passed to test() must be of the type array, integer given, called in %s on line %d and defined" +string(%d) "Argument 3 passed to test() must be of the type array, integer given, called in %s on line %d and defined in %s on line %d" diff --git a/Zend/zend.c b/Zend/zend.c index 8ed8b2abc1..f54442a7ed 100644 --- a/Zend/zend.c +++ b/Zend/zend.c @@ -1284,7 +1284,7 @@ ZEND_API void zend_type_error(const char *format, ...) /* {{{ */ va_start(va, format); zend_vspprintf(&message, 0, format, va); - zend_throw_exception(zend_get_type_exception(), message, 0); + zend_throw_exception(zend_get_type_exception(), message, E_ERROR); efree(message); va_end(va); } /* }}} */ diff --git a/Zend/zend_execute.c b/Zend/zend_execute.c index 2b1a83c20e..0fed841697 100644 --- a/Zend/zend_execute.c +++ b/Zend/zend_execute.c @@ -867,9 +867,32 @@ ZEND_API void zend_verify_return_error(const zend_function *zf, const char *need fclass = ""; } - zend_type_error("Return value of %s%s%s() must %s%s, %s%s returned in %s on line %d", - fclass, fsep, fname, need_msg, need_kind, returned_msg, returned_kind, - zf->op_array.filename->val, EG(current_execute_data)->opline->lineno); + if (zf->common.type == ZEND_USER_FUNCTION) { + zend_type_error("Return value of %s%s%s() must %s%s, %s%s returned in %s on line %d", + fclass, fsep, fname, need_msg, need_kind, returned_msg, returned_kind, + zf->op_array.filename->val, EG(current_execute_data)->opline->lineno); + } else { + zend_type_error("Return value of %s%s%s() must %s%s, %s%s returned", + fclass, fsep, fname, need_msg, need_kind, returned_msg, returned_kind); + } +} + +ZEND_API void zend_verify_internal_return_error(const zend_function *zf, const char *need_msg, const char *need_kind, const char *returned_msg, const char *returned_kind) +{ + const char *fname = zf->common.function_name->val; + const char *fsep; + const char *fclass; + + if (zf->common.scope) { + fsep = "::"; + fclass = zf->common.scope->name->val; + } else { + fsep = ""; + fclass = ""; + } + + zend_error(E_CORE_ERROR, "Return value of %s%s%s() must %s%s, %s%s returned", + fclass, fsep, fname, need_msg, need_kind, returned_msg, returned_kind); } #if ZEND_DEBUG @@ -885,30 +908,30 @@ static int zend_verify_internal_return_type(zend_function *zf, zval *ret, zend_b 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_return_error(zf, need_msg, class_name, "instance of ", Z_OBJCE_P(ret)->name->val); + 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_return_error(zf, need_msg, class_name, zend_zval_type_name(ret), ""); + 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_return_error(zf, "be of the type array", "", zend_zval_type_name(ret), ""); + 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_return_error(zf, "be callable", "", zend_zval_type_name(ret), ""); + zend_verify_internal_return_error(zf, "be callable", "", zend_zval_type_name(ret), ""); return 0; } } else if (UNEXPECTED(!ZEND_SAME_FAKE_TYPE(ret_info->type_hint, Z_TYPE_P(ret)))) { if (Z_TYPE_P(ret) == IS_NULL) { if (!ret_info->allow_null) { failure: - zend_verify_return_error(zf, "be of the type ", zend_get_type_by_const(ret_info->type_hint), zend_zval_type_name(ret), ""); + 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; } diff --git a/Zend/zend_execute.h b/Zend/zend_execute.h index c040c8f633..239185ccb7 100644 --- a/Zend/zend_execute.h +++ b/Zend/zend_execute.h @@ -51,6 +51,7 @@ ZEND_API char * zend_verify_internal_arg_class_kind(const zend_internal_arg_info ZEND_API char * zend_verify_arg_class_kind(const zend_arg_info *cur_arg_info, char **class_name, zend_class_entry **pce); ZEND_API void zend_verify_arg_error(const zend_function *zf, uint32_t arg_num, const char *need_msg, const char *need_kind, const char *given_msg, const char *given_kind, zval *arg); 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); +ZEND_API void zend_verify_internal_return_error(const zend_function *zf, const char *need_msg, const char *need_kind, const char *returned_msg, const char *returned_kind); static zend_always_inline zval* zend_assign_to_variable(zval *variable_ptr, zval *value, zend_uchar value_type) { diff --git a/Zend/zend_vm_def.h b/Zend/zend_vm_def.h index da8052c97b..0643995314 100644 --- a/Zend/zend_vm_def.h +++ b/Zend/zend_vm_def.h @@ -3214,6 +3214,8 @@ ZEND_VM_HANDLER(129, ZEND_DO_ICALL, ANY, ANY) zend_function *fbc = call->func; zval *ret; + ZEND_ADD_CALL_FLAG(call, opline->op1.num & ZEND_CALL_STRICT_TYPEHINTS); + SAVE_OPLINE(); EX(call) = call->prev_execute_data; @@ -3261,6 +3263,8 @@ ZEND_VM_HANDLER(130, ZEND_DO_UCALL, ANY, ANY) zend_function *fbc = call->func; zval *ret; + ZEND_ADD_CALL_FLAG(call, opline->op1.num & ZEND_CALL_STRICT_TYPEHINTS); + SAVE_OPLINE(); EX(call) = call->prev_execute_data; @@ -3286,6 +3290,8 @@ ZEND_VM_HANDLER(131, ZEND_DO_FCALL_BY_NAME, ANY, ANY) zend_function *fbc = call->func; zval *ret; + ZEND_ADD_CALL_FLAG(call, opline->op1.num & ZEND_CALL_STRICT_TYPEHINTS); + SAVE_OPLINE(); EX(call) = call->prev_execute_data; diff --git a/Zend/zend_vm_execute.h b/Zend/zend_vm_execute.h index c9b09c7bc4..72d3fedfb2 100644 --- a/Zend/zend_vm_execute.h +++ b/Zend/zend_vm_execute.h @@ -545,6 +545,8 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_DO_ICALL_SPEC_HANDLER(ZEND_OPC zend_function *fbc = call->func; zval *ret; + ZEND_ADD_CALL_FLAG(call, opline->op1.num & ZEND_CALL_STRICT_TYPEHINTS); + SAVE_OPLINE(); EX(call) = call->prev_execute_data; @@ -592,6 +594,8 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_DO_UCALL_SPEC_HANDLER(ZEND_OPC zend_function *fbc = call->func; zval *ret; + ZEND_ADD_CALL_FLAG(call, opline->op1.num & ZEND_CALL_STRICT_TYPEHINTS); + SAVE_OPLINE(); EX(call) = call->prev_execute_data; @@ -617,6 +621,8 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_DO_FCALL_BY_NAME_SPEC_HANDLER( zend_function *fbc = call->func; zval *ret; + ZEND_ADD_CALL_FLAG(call, opline->op1.num & ZEND_CALL_STRICT_TYPEHINTS); + SAVE_OPLINE(); EX(call) = call->prev_execute_data; diff --git a/tests/lang/catchable_error_002.phpt b/tests/lang/catchable_error_002.phpt index a80928523b..04e19897f4 100644 --- a/tests/lang/catchable_error_002.phpt +++ b/tests/lang/catchable_error_002.phpt @@ -25,5 +25,5 @@ Catchable fatal error [2] echo "ALIVE!\n"; ?> --EXPECTF-- -Argument 1 passed to blah() must be an instance of Foo, instance of stdClass given, called in %scatchable_error_002.php on line 18 and defined +Argument 1 passed to blah() must be an instance of Foo, instance of stdClass given, called in %scatchable_error_002.php on line %d and defined in %scatchable_error_002.php on line %d ALIVE! -- 2.40.0