From: Anthony Ferrara Date: Wed, 18 Mar 2015 16:23:09 +0000 (-0400) Subject: Refactor error implementation significantly to centralize error mode behavior. Add... X-Git-Tag: PRE_PHP7_NSAPI_REMOVAL~573^2~11^2~18 X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=7feebead1b70714c45bf302e0356b4cb8047fba0;p=php Refactor error implementation significantly to centralize error mode behavior. Add zend_internal_type_error() function --- diff --git a/Zend/tests/typehints/scalar_basic.phpt b/Zend/tests/typehints/scalar_basic.phpt index af10b559ef..df1abe2607 100644 --- a/Zend/tests/typehints/scalar_basic.phpt +++ b/Zend/tests/typehints/scalar_basic.phpt @@ -6,7 +6,6 @@ Scalar type hint basics $errnames = [ E_NOTICE => 'E_NOTICE', E_WARNING => 'E_WARNING', - E_RECOVERABLE_ERROR => 'E_RECOVERABLE_ERROR' ]; set_error_handler(function (int $errno, string $errmsg, string $file, int $line) use ($errnames) { echo "$errnames[$errno]: $errmsg on line $line\n"; @@ -48,194 +47,231 @@ $values = [ foreach ($functions as $type => $function) { echo PHP_EOL, "Testing '$type' typehint:", PHP_EOL; foreach ($values as $value) { - echo "*** Trying "; + echo PHP_EOL . "*** Trying "; var_dump($value); - var_dump($function($value)); + try { + var_dump($function($value)); + } catch (\TypeException $e) { + echo "*** Caught " . $e->getMessage() . PHP_EOL; + } } } +echo PHP_EOL . "Done"; +?> --EXPECTF-- Testing 'int' typehint: + *** Trying int(1) int(1) + *** Trying string(1) "1" int(1) + *** Trying float(1) int(1) + *** Trying float(1.5) int(1) + *** Trying string(2) "1a" E_NOTICE: A non well formed numeric value encountered on line %d int(1) + *** Trying string(1) "a" -E_RECOVERABLE_ERROR: Argument 1 passed to {closure}() must be of the type integer, string given, called in %s on line %d and defined on line %d -string(1) "a" +*** Caught Argument 1 passed to {closure}() must be of the type integer, string given, called in %s on line %d and defined in %s on line %d + *** Trying string(0) "" -E_RECOVERABLE_ERROR: Argument 1 passed to {closure}() must be of the type integer, string given, called in %s on line %d and defined on line %d -string(0) "" +*** Caught Argument 1 passed to {closure}() must be of the type integer, string given, called in %s on line %d and defined in %s on line %d + *** Trying int(%d) int(%d) + *** Trying float(NAN) -E_RECOVERABLE_ERROR: Argument 1 passed to {closure}() must be of the type integer, float given, called in %s on line %d and defined on line %d -float(NAN) +*** Caught Argument 1 passed to {closure}() must be of the type integer, float given, called in %s on line %d and defined in %s on line %d + *** Trying bool(true) int(1) + *** Trying bool(false) int(0) + *** Trying NULL -E_RECOVERABLE_ERROR: Argument 1 passed to {closure}() must be of the type integer, null given, called in %s on line %d and defined on line %d -NULL +*** Caught Argument 1 passed to {closure}() must be of the type integer, null given, called in %s on line %d and defined in %s on line %d + *** Trying array(0) { } -E_RECOVERABLE_ERROR: Argument 1 passed to {closure}() must be of the type integer, array given, called in %s on line %d and defined on line %d -array(0) { -} +*** Caught Argument 1 passed to {closure}() must be of the type integer, array given, called in %s on line %d and defined in %s on line %d + *** Trying object(stdClass)#%s (0) { } -E_RECOVERABLE_ERROR: Argument 1 passed to {closure}() must be of the type integer, object given, called in %s on line %d and defined on line %d -object(stdClass)#%s (0) { -} +*** Caught Argument 1 passed to {closure}() must be of the type integer, object given, called in %s on line %d and defined in %s on line %d + *** Trying object(Stringable)#%s (0) { } -E_RECOVERABLE_ERROR: Argument 1 passed to {closure}() must be of the type integer, object given, called in %s on line %d and defined on line %d -object(Stringable)#%s (0) { -} +*** Caught Argument 1 passed to {closure}() must be of the type integer, object given, called in %s on line %d and defined in %s on line %d + *** Trying resource(%d) of type (stream) -E_RECOVERABLE_ERROR: Argument 1 passed to {closure}() must be of the type integer, resource given, called in %s on line %d and defined on line %d -resource(%d) of type (stream) +*** Caught Argument 1 passed to {closure}() must be of the type integer, resource given, called in %s on line %d and defined in %s on line %d Testing 'float' typehint: + *** Trying int(1) float(1) + *** Trying string(1) "1" float(1) + *** Trying float(1) float(1) + *** Trying float(1.5) float(1.5) + *** Trying string(2) "1a" E_NOTICE: A non well formed numeric value encountered on line %d float(1) + *** Trying string(1) "a" -E_RECOVERABLE_ERROR: Argument 1 passed to {closure}() must be of the type float, string given, called in %s on line %d and defined on line %d -string(1) "a" +*** Caught Argument 1 passed to {closure}() must be of the type float, string given, called in %s on line %d and defined in %s on line %d + *** Trying string(0) "" -E_RECOVERABLE_ERROR: Argument 1 passed to {closure}() must be of the type float, string given, called in %s on line %d and defined on line %d -string(0) "" +*** Caught Argument 1 passed to {closure}() must be of the type float, string given, called in %s on line %d and defined in %s on line %d + *** Trying int(%d) float(%s) + *** Trying float(NAN) float(NAN) + *** Trying bool(true) float(1) + *** Trying bool(false) float(0) + *** Trying NULL -E_RECOVERABLE_ERROR: Argument 1 passed to {closure}() must be of the type float, null given, called in %s on line %d and defined on line %d -NULL +*** Caught Argument 1 passed to {closure}() must be of the type float, null given, called in %s on line %d and defined in %s on line %d + *** Trying array(0) { } -E_RECOVERABLE_ERROR: Argument 1 passed to {closure}() must be of the type float, array given, called in %s on line %d and defined on line %d -array(0) { -} +*** Caught Argument 1 passed to {closure}() must be of the type float, array given, called in %s on line %d and defined in %s on line %d + *** Trying object(stdClass)#%s (0) { } -E_RECOVERABLE_ERROR: Argument 1 passed to {closure}() must be of the type float, object given, called in %s on line %d and defined on line %d -object(stdClass)#%s (0) { -} +*** Caught Argument 1 passed to {closure}() must be of the type float, object given, called in %s on line %d and defined in %s on line %d + *** Trying object(Stringable)#%s (0) { } -E_RECOVERABLE_ERROR: Argument 1 passed to {closure}() must be of the type float, object given, called in %s on line %d and defined on line %d -object(Stringable)#%s (0) { -} +*** Caught Argument 1 passed to {closure}() must be of the type float, object given, called in %s on line %d and defined in %s on line %d + *** Trying resource(%d) of type (stream) -E_RECOVERABLE_ERROR: Argument 1 passed to {closure}() must be of the type float, resource given, called in %s on line %d and defined on line %d -resource(%d) of type (stream) +*** Caught Argument 1 passed to {closure}() must be of the type float, resource given, called in %s on line %d and defined in %s on line %d Testing 'string' typehint: + *** Trying int(1) string(1) "1" + *** Trying string(1) "1" string(1) "1" + *** Trying float(1) string(1) "1" + *** Trying float(1.5) string(3) "1.5" + *** Trying string(2) "1a" string(2) "1a" + *** Trying string(1) "a" string(1) "a" + *** Trying string(0) "" string(0) "" + *** Trying int(%d) string(%d) "%d" + *** Trying float(NAN) string(3) "NAN" + *** Trying bool(true) string(1) "1" + *** Trying bool(false) string(0) "" + *** Trying NULL -E_RECOVERABLE_ERROR: Argument 1 passed to {closure}() must be of the type string, null given, called in %s on line %d and defined on line %d -NULL +*** Caught Argument 1 passed to {closure}() must be of the type string, null given, called in %s on line %d and defined in %s on line %d + *** Trying array(0) { } -E_RECOVERABLE_ERROR: Argument 1 passed to {closure}() must be of the type string, array given, called in %s on line %d and defined on line %d -array(0) { -} +*** Caught Argument 1 passed to {closure}() must be of the type string, array given, called in %s on line %d and defined in %s on line %d + *** Trying object(stdClass)#%s (0) { } -E_RECOVERABLE_ERROR: Argument 1 passed to {closure}() must be of the type string, object given, called in %s on line %d and defined on line %d -object(stdClass)#%s (0) { -} +*** Caught Argument 1 passed to {closure}() must be of the type string, object given, called in %s on line %d and defined in %s on line %d + *** Trying object(Stringable)#%s (0) { } string(6) "foobar" + *** Trying resource(%d) of type (stream) -E_RECOVERABLE_ERROR: Argument 1 passed to {closure}() must be of the type string, resource given, called in %s on line %d and defined on line %d -resource(%d) of type (stream) +*** Caught Argument 1 passed to {closure}() must be of the type string, resource given, called in %s on line %d and defined in %s on line %d Testing 'bool' typehint: + *** Trying int(1) bool(true) + *** Trying string(1) "1" bool(true) + *** Trying float(1) bool(true) + *** Trying float(1.5) bool(true) + *** Trying string(2) "1a" bool(true) + *** Trying string(1) "a" bool(true) + *** Trying string(0) "" bool(false) + *** Trying int(%d) bool(true) + *** Trying float(NAN) bool(true) + *** Trying bool(true) bool(true) + *** Trying bool(false) bool(false) + *** Trying NULL -E_RECOVERABLE_ERROR: Argument 1 passed to {closure}() must be of the type boolean, null given, called in %s on line %d and defined on line %d -NULL +*** Caught Argument 1 passed to {closure}() must be of the type boolean, null given, called in %s on line %d and defined in %s on line %d + *** Trying array(0) { } -E_RECOVERABLE_ERROR: Argument 1 passed to {closure}() must be of the type boolean, array given, called in %s on line %d and defined on line %d -array(0) { -} +*** Caught Argument 1 passed to {closure}() must be of the type boolean, array given, called in %s on line %d and defined in %s on line %d + *** Trying object(stdClass)#%s (0) { } -E_RECOVERABLE_ERROR: Argument 1 passed to {closure}() must be of the type boolean, object given, called in %s on line %d and defined on line %d -object(stdClass)#%s (0) { -} +*** Caught Argument 1 passed to {closure}() must be of the type boolean, object given, called in %s on line %d and defined in %s on line %d + *** Trying object(Stringable)#%s (0) { } -E_RECOVERABLE_ERROR: Argument 1 passed to {closure}() must be of the type boolean, object given, called in %s on line %d and defined on line %d -object(Stringable)#%s (0) { -} +*** Caught Argument 1 passed to {closure}() must be of the type boolean, object given, called in %s on line %d and defined in %s on line %d + *** Trying resource(%d) of type (stream) -E_RECOVERABLE_ERROR: Argument 1 passed to {closure}() must be of the type boolean, resource given, called in %s on line %d and defined on line %d -resource(%d) of type (stream) +*** Caught Argument 1 passed to {closure}() must be of the type boolean, resource given, called in %s on line %d and defined in %s on line %d + +Done \ No newline at end of file diff --git a/Zend/zend.c b/Zend/zend.c index fe507d7154..8ed8b2abc1 100644 --- a/Zend/zend.c +++ b/Zend/zend.c @@ -1277,6 +1277,35 @@ ZEND_API ZEND_NORETURN void zend_error_noreturn(int type, const char *format, .. # endif #endif +ZEND_API void zend_type_error(const char *format, ...) /* {{{ */ +{ + va_list va; + char *message = NULL; + + va_start(va, format); + zend_vspprintf(&message, 0, format, va); + zend_throw_exception(zend_get_type_exception(), message, 0); + efree(message); + va_end(va); +} /* }}} */ + +ZEND_API void zend_internal_type_error(zend_bool strict, const char *format, ...) /* {{{ */ +{ + va_list va; + char *message = NULL; + + va_start(va, format); + zend_vspprintf(&message, 0, format, va); + if (strict) { + zend_throw_exception(zend_get_type_exception(), message, 0); + } else { + zend_error(E_WARNING, message); + } + efree(message); + + va_end(va); +} /* }}} */ + ZEND_API void zend_output_debug_string(zend_bool trigger_break, const char *format, ...) /* {{{ */ { #if ZEND_DEBUG diff --git a/Zend/zend.h b/Zend/zend.h index 94cab74af1..db132a583a 100644 --- a/Zend/zend.h +++ b/Zend/zend.h @@ -285,6 +285,8 @@ extern ZEND_API char *(*zend_getenv)(char *name, size_t name_len); extern ZEND_API zend_string *(*zend_resolve_path)(const char *filename, int filename_len); ZEND_API void zend_error(int type, const char *format, ...) ZEND_ATTRIBUTE_FORMAT(printf, 2, 3); +ZEND_API void zend_type_error(const char *format, ...); +ZEND_API void zend_internal_type_error(zend_bool strict, const char *format, ...); void zenderror(const char *error); diff --git a/Zend/zend_API.c b/Zend/zend_API.c index 02eab229f0..af389623a3 100644 --- a/Zend/zend_API.c +++ b/Zend/zend_API.c @@ -153,9 +153,8 @@ ZEND_API void _zend_wrong_param_count(zend_bool strict) /* {{{ */ { const char *space; const char *class_name = get_active_class_name(&space); - int error_type = strict ? (E_EXCEPTION | E_ERROR) : E_WARNING; - zend_error(error_type, "Wrong parameter count for %s%s%s()", class_name, space, get_active_function_name()); + zend_internal_type_error(strict, "Wrong parameter count for %s%s%s()", class_name, space, get_active_function_name()); } /* }}} */ @@ -239,9 +238,8 @@ ZEND_API void zend_wrong_paramers_count_error(int num_args, int min_num_args, in { zend_function *active_function = EG(current_execute_data)->func; const char *class_name = active_function->common.scope ? active_function->common.scope->name->val : ""; - int error_type = strict ? (E_EXCEPTION | E_ERROR) : E_WARNING; - zend_error(error_type, "%s%s%s() expects %s %d parameter%s, %d given", + zend_internal_type_error(strict, "%s%s%s() expects %s %d parameter%s, %d given", class_name, \ class_name[0] ? "::" : "", \ active_function->common.function_name->val, @@ -260,9 +258,8 @@ ZEND_API void zend_wrong_paramer_type_error(int num, zend_expected_type expected Z_EXPECTED_TYPES(Z_EXPECTED_TYPE_STR) NULL }; - int error_type = strict ? (E_EXCEPTION | E_ERROR) : E_WARNING; - zend_error(error_type, "%s%s%s() expects parameter %d to be %s, %s given", + zend_internal_type_error(strict, "%s%s%s() expects parameter %d to be %s, %s given", class_name, space, get_active_function_name(), num, expected_error[expected_type], zend_zval_type_name(arg)); } /* }}} */ @@ -271,9 +268,8 @@ ZEND_API void zend_wrong_paramer_class_error(int num, char *name, zval *arg, zen { const char *space; const char *class_name = get_active_class_name(&space); - int error_type = strict ? (E_EXCEPTION | E_ERROR) : E_WARNING; - zend_error(error_type, "%s%s%s() expects parameter %d to be %s, %s given", + zend_internal_type_error(strict, "%s%s%s() expects parameter %d to be %s, %s given", class_name, space, get_active_function_name(), num, name, zend_zval_type_name(arg)); } /* }}} */ @@ -292,7 +288,6 @@ ZEND_API void zend_wrong_callback_error(int severity, int num, char *error) /* { ZEND_API int zend_parse_arg_class(zval *arg, zend_class_entry **pce, int num, int check_null, zend_bool strict) /* {{{ */ { zend_class_entry *ce_base = *pce; - int error_type = strict ? (E_EXCEPTION | E_ERROR) : E_WARNING; if (check_null && Z_TYPE_P(arg) == IS_NULL) { *pce = NULL; @@ -305,7 +300,7 @@ ZEND_API int zend_parse_arg_class(zval *arg, zend_class_entry **pce, int num, in const char *space; const char *class_name = get_active_class_name(&space); - zend_error(error_type, "%s%s%s() expects parameter %d to be a class name derived from %s, '%s' given", + zend_internal_type_error(strict, "%s%s%s() expects parameter %d to be a class name derived from %s, '%s' given", class_name, space, get_active_function_name(), num, ce_base->name->val, Z_STRVAL_P(arg)); *pce = NULL; @@ -316,7 +311,7 @@ ZEND_API int zend_parse_arg_class(zval *arg, zend_class_entry **pce, int num, in const char *space; const char *class_name = get_active_class_name(&space); - zend_error(error_type, "%s%s%s() expects parameter %d to be a valid class name, '%s' given", + zend_internal_type_error(strict, "%s%s%s() expects parameter %d to be a valid class name, '%s' given", class_name, space, get_active_function_name(), num, Z_STRVAL_P(arg)); return 0; @@ -580,7 +575,6 @@ static int zend_parse_arg(int arg_num, zval *arg, va_list *va, const char **spec { const char *expected_type = NULL; char *error = NULL; - int error_type = strict ? (E_EXCEPTION | E_ERROR) : E_WARNING; int severity; expected_type = zend_parse_arg_impl(arg_num, arg, va, spec, &error, &severity, strict); @@ -590,11 +584,11 @@ static int zend_parse_arg(int arg_num, zval *arg, va_list *va, const char **spec const char *class_name = get_active_class_name(&space); if (error) { - zend_error(error_type, "%s%s%s() expects parameter %d %s", - class_name, space, get_active_function_name(), arg_num, error); + zend_internal_type_error(strict, "%s%s%s() expects parameter %d %s", + class_name, space, get_active_function_name(), arg_num, error); efree(error); } else { - zend_error(error_type, "%s%s%s() expects parameter %d to be %s, %s given", + zend_internal_type_error(strict, "%s%s%s() expects parameter %d to be %s, %s given", class_name, space, get_active_function_name(), arg_num, expected_type, zend_zval_type_name(arg)); } @@ -636,7 +630,6 @@ static int zend_parse_va_args(int num_args, const char *type_spec, va_list *va, zend_bool have_varargs = 0; zval **varargs = NULL; int *n_varargs = NULL; - int error_type = strict ? (E_EXCEPTION | E_ERROR) : E_WARNING; for (spec_walk = type_spec; *spec_walk; spec_walk++) { c = *spec_walk; @@ -670,7 +663,7 @@ static int zend_parse_va_args(int num_args, const char *type_spec, va_list *va, zend_function *active_function = EG(current_execute_data)->func; const char *class_name = active_function->common.scope ? active_function->common.scope->name->val : ""; - zend_error(error_type, "%s%s%s(): only one varargs specifier (* or +) is permitted", + zend_error(E_WARNING, "%s%s%s(): only one varargs specifier (* or +) is permitted", class_name, class_name[0] ? "::" : "", active_function->common.function_name->val); @@ -690,7 +683,7 @@ static int zend_parse_va_args(int num_args, const char *type_spec, va_list *va, if (!quiet) { zend_function *active_function = EG(current_execute_data)->func; const char *class_name = active_function->common.scope ? active_function->common.scope->name->val : ""; - zend_error(error_type, "%s%s%s(): bad type specifier while parsing parameters", + zend_error(E_WARNING, "%s%s%s(): bad type specifier while parsing parameters", class_name, class_name[0] ? "::" : "", active_function->common.function_name->val); @@ -713,7 +706,7 @@ static int zend_parse_va_args(int num_args, const char *type_spec, va_list *va, if (!quiet) { zend_function *active_function = EG(current_execute_data)->func; const char *class_name = active_function->common.scope ? active_function->common.scope->name->val : ""; - zend_error(error_type, "%s%s%s() expects %s %d parameter%s, %d given", + zend_internal_type_error(strict, "%s%s%s() expects %s %d parameter%s, %d given", class_name, class_name[0] ? "::" : "", active_function->common.function_name->val, @@ -728,7 +721,7 @@ static int zend_parse_va_args(int num_args, const char *type_spec, va_list *va, arg_count = ZEND_CALL_NUM_ARGS(EG(current_execute_data)); if (num_args > arg_count) { - zend_error(error_type, "%s(): could not obtain parameters for parsing", + zend_error(E_WARNING, "%s(): could not obtain parameters for parsing", get_active_function_name()); return FAILURE; } @@ -782,7 +775,7 @@ static int zend_parse_va_args(int num_args, const char *type_spec, va_list *va, if (0 == (type_spec)[0] && 0 != __num_args && !(flags & ZEND_PARSE_PARAMS_QUIET)) { \ const char *__space; \ const char * __class_name = get_active_class_name(&__space); \ - zend_error((flags & ZEND_PARSE_PARAMS_STRICT) ? (E_EXCEPTION | E_ERROR) : E_WARNING, "%s%s%s() expects exactly 0 parameters, %d given", \ + zend_internal_type_error((flags & ZEND_PARSE_PARAMS_STRICT), "%s%s%s() expects exactly 0 parameters, %d given", \ __class_name, __space, \ get_active_function_name(), __num_args); \ return FAILURE; \ diff --git a/Zend/zend_exceptions.c b/Zend/zend_exceptions.c index 7070934426..2a8af1bf28 100644 --- a/Zend/zend_exceptions.c +++ b/Zend/zend_exceptions.c @@ -35,6 +35,7 @@ static zend_class_entry *default_exception_ce; static zend_class_entry *error_exception_ce; static zend_class_entry *engine_exception_ce; static zend_class_entry *parse_exception_ce; +static zend_class_entry *type_exception_ce; static zend_object_handlers default_exception_handlers; ZEND_API void (*zend_throw_exception_hook)(zval *ex); @@ -778,6 +779,10 @@ void zend_register_default_exception(void) /* {{{ */ INIT_CLASS_ENTRY(ce, "ParseException", NULL); parse_exception_ce = zend_register_internal_class_ex(&ce, base_exception_ce); parse_exception_ce->create_object = zend_default_exception_new; + + INIT_CLASS_ENTRY(ce, "TypeException", NULL); + type_exception_ce = zend_register_internal_class_ex(&ce, engine_exception_ce); + type_exception_ce->create_object = zend_default_exception_new; } /* }}} */ @@ -811,6 +816,12 @@ ZEND_API zend_class_entry *zend_get_parse_exception(void) /* {{{ */ } /* }}} */ +ZEND_API zend_class_entry *zend_get_type_exception(void) /* {{{ */ +{ + return type_exception_ce; +} +/* }}} */ + ZEND_API zend_object *zend_throw_exception(zend_class_entry *exception_ce, const char *message, zend_long code) /* {{{ */ { @@ -892,7 +903,7 @@ ZEND_API void zend_exception_error(zend_object *ex, int severity) /* {{{ */ ZVAL_OBJ(&exception, ex); ce_exception = Z_OBJCE(exception); EG(exception) = NULL; - if (ce_exception == parse_exception_ce || ce_exception == engine_exception_ce) { + if (ce_exception == parse_exception_ce || ce_exception == engine_exception_ce || ce_exception == type_exception_ce) { zend_string *message = zval_get_string(GET_PROPERTY(&exception, "message")); zend_string *file = zval_get_string(GET_PROPERTY_SILENT(&exception, "file")); zend_long line = zval_get_long(GET_PROPERTY_SILENT(&exception, "line")); diff --git a/Zend/zend_exceptions.h b/Zend/zend_exceptions.h index 10609fecb6..e2c1f1fac7 100644 --- a/Zend/zend_exceptions.h +++ b/Zend/zend_exceptions.h @@ -39,6 +39,7 @@ ZEND_API zend_class_entry *zend_exception_get_default(void); ZEND_API zend_class_entry *zend_get_error_exception(void); ZEND_API zend_class_entry *zend_get_engine_exception(void); ZEND_API zend_class_entry *zend_get_parse_exception(void); +ZEND_API zend_class_entry *zend_get_type_exception(void); ZEND_API void zend_register_default_classes(void); /* exception_ce NULL or zend_exception_get_default() or a derived class diff --git a/Zend/zend_execute.c b/Zend/zend_execute.c index 4321c0f330..36bf6b1bea 100644 --- a/Zend/zend_execute.c +++ b/Zend/zend_execute.c @@ -598,7 +598,7 @@ ZEND_API char * zend_verify_arg_class_kind(const zend_arg_info *cur_arg_info, ch } } -ZEND_API void zend_verify_arg_error(int error_type, 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_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_execute_data *ptr = EG(current_execute_data)->prev_execute_data; const char *fname = zf->common.function_name->val; @@ -621,16 +621,19 @@ ZEND_API void zend_verify_arg_error(int error_type, const zend_function *zf, uin } if (ptr && ptr->func && ZEND_USER_CODE(ptr->func->common.type)) { - zend_error(error_type, "Argument %d passed to %s%s%s() must %s%s, %s%s given, called in %s on line %d and defined", arg_num, fclass, fsep, fname, need_msg, need_kind, given_msg, given_kind, ptr->func->op_array.filename->val, ptr->opline->lineno); + zend_type_error("Argument %d passed to %s%s%s() must %s%s, %s%s given, called in %s on line %d and defined in %s on line %d", + arg_num, fclass, fsep, fname, need_msg, need_kind, given_msg, given_kind, + ptr->func->op_array.filename->val, ptr->opline->lineno, + zf->op_array.filename->val, EG(current_execute_data)->opline->lineno); } 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); + zend_type_error("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); } if (arg) { ZVAL_COPY_VALUE(arg, &old_arg); } } 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); + zend_type_error("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); } } @@ -717,27 +720,27 @@ static void zend_verify_internal_arg_type(zend_function *zf, uint32_t arg_num, z if (Z_TYPE_P(arg) == IS_OBJECT) { need_msg = zend_verify_internal_arg_class_kind((zend_internal_arg_info*)cur_arg_info, &class_name, &ce); if (!ce || !instanceof_function(Z_OBJCE_P(arg), ce)) { - zend_verify_arg_error(E_EXCEPTION | E_ERROR, zf, arg_num, need_msg, class_name, "instance of ", Z_OBJCE_P(arg)->name->val, arg); + zend_verify_arg_error(zf, arg_num, need_msg, class_name, "instance of ", Z_OBJCE_P(arg)->name->val, arg); } } else if (Z_TYPE_P(arg) != IS_NULL || !cur_arg_info->allow_null) { need_msg = zend_verify_internal_arg_class_kind((zend_internal_arg_info*)cur_arg_info, &class_name, &ce); - zend_verify_arg_error(E_EXCEPTION | E_ERROR, zf, arg_num, need_msg, class_name, zend_zval_type_name(arg), "", arg); + zend_verify_arg_error(zf, arg_num, need_msg, class_name, zend_zval_type_name(arg), "", arg); } } else if (cur_arg_info->type_hint) { ZVAL_DEREF(arg); if (cur_arg_info->type_hint == IS_ARRAY) { if (Z_TYPE_P(arg) != IS_ARRAY && (Z_TYPE_P(arg) != IS_NULL || !cur_arg_info->allow_null)) { - zend_verify_arg_error(E_EXCEPTION | E_ERROR, zf, arg_num, "be of the type array", "", zend_zval_type_name(arg), "", arg); + zend_verify_arg_error(zf, arg_num, "be of the type array", "", zend_zval_type_name(arg), "", arg); } } else if (cur_arg_info->type_hint == IS_CALLABLE) { if (!zend_is_callable(arg, IS_CALLABLE_CHECK_SILENT, NULL) && (Z_TYPE_P(arg) != IS_NULL || !cur_arg_info->allow_null)) { - zend_verify_arg_error(E_EXCEPTION | E_ERROR, zf, arg_num, "be callable", "", zend_zval_type_name(arg), "", arg); + zend_verify_arg_error(zf, arg_num, "be callable", "", zend_zval_type_name(arg), "", arg); } } else if (UNEXPECTED(!ZEND_SAME_FAKE_TYPE(cur_arg_info->type_hint, Z_TYPE_P(arg)))) { if (Z_TYPE_P(arg) == IS_NULL) { if (!cur_arg_info->allow_null) { failure: - zend_verify_arg_error(E_EXCEPTION | E_ERROR, zf, arg_num, "be of the type ", zend_get_type_by_const(cur_arg_info->type_hint), zend_zval_type_name(arg), "", arg); + 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; } @@ -769,27 +772,27 @@ static void zend_verify_arg_type(zend_function *zf, uint32_t arg_num, zval *arg, if (Z_TYPE_P(arg) == IS_OBJECT) { 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(E_EXCEPTION | E_ERROR, zf, arg_num, need_msg, class_name, "instance of ", Z_OBJCE_P(arg)->name->val, arg); + zend_verify_arg_error(zf, arg_num, need_msg, class_name, "instance of ", Z_OBJCE_P(arg)->name->val, arg); } } else if (Z_TYPE_P(arg) != IS_NULL || !(cur_arg_info->allow_null || (default_value && is_null_constant(default_value)))) { need_msg = zend_verify_arg_class_kind(cur_arg_info, &class_name, &ce); - zend_verify_arg_error(E_EXCEPTION | E_ERROR, zf, arg_num, need_msg, class_name, zend_zval_type_name(arg), "", arg); + zend_verify_arg_error(zf, arg_num, need_msg, class_name, zend_zval_type_name(arg), "", arg); } } else if (cur_arg_info->type_hint) { ZVAL_DEREF(arg); if (cur_arg_info->type_hint == IS_ARRAY) { if (Z_TYPE_P(arg) != IS_ARRAY && (Z_TYPE_P(arg) != IS_NULL || !(cur_arg_info->allow_null || (default_value && is_null_constant(default_value))))) { - zend_verify_arg_error(E_EXCEPTION | E_ERROR, zf, arg_num, "be of the type array", "", zend_zval_type_name(arg), "", arg); + zend_verify_arg_error(zf, arg_num, "be of the type array", "", zend_zval_type_name(arg), "", arg); } } else if (cur_arg_info->type_hint == IS_CALLABLE) { if (!zend_is_callable(arg, IS_CALLABLE_CHECK_SILENT, NULL) && (Z_TYPE_P(arg) != IS_NULL || !(cur_arg_info->allow_null || (default_value && is_null_constant(default_value))))) { - zend_verify_arg_error(E_EXCEPTION | E_ERROR, zf, arg_num, "be callable", "", zend_zval_type_name(arg), "", arg); + zend_verify_arg_error(zf, arg_num, "be callable", "", zend_zval_type_name(arg), "", arg); } } else if (UNEXPECTED(!ZEND_SAME_FAKE_TYPE(cur_arg_info->type_hint, Z_TYPE_P(arg)))) { if (Z_TYPE_P(arg) == IS_NULL) { if (!cur_arg_info->allow_null) { failure: - zend_verify_arg_error(E_EXCEPTION | E_ERROR, zf, arg_num, "be of the type ", zend_get_type_by_const(cur_arg_info->type_hint), zend_zval_type_name(arg), "", arg); + 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; } @@ -818,15 +821,15 @@ static inline int zend_verify_missing_arg_type(zend_function *zf, uint32_t arg_n char *class_name; need_msg = zend_verify_arg_class_kind(cur_arg_info, &class_name, &ce); - zend_verify_arg_error(E_EXCEPTION | E_ERROR, zf, arg_num, need_msg, class_name, "none", "", NULL); + zend_verify_arg_error(zf, arg_num, need_msg, class_name, "none", "", NULL); return 0; } else if (cur_arg_info->type_hint) { if (cur_arg_info->type_hint == IS_ARRAY) { - zend_verify_arg_error(E_EXCEPTION | E_ERROR, zf, arg_num, "be of the type array", "", "none", "", NULL); + zend_verify_arg_error(zf, arg_num, "be of the type array", "", "none", "", NULL); } else if (cur_arg_info->type_hint == IS_CALLABLE) { - zend_verify_arg_error(E_EXCEPTION | E_ERROR, zf, arg_num, "be callable", "", "none", "", NULL); + zend_verify_arg_error(zf, arg_num, "be callable", "", "none", "", NULL); } else { - zend_verify_arg_error(E_EXCEPTION | E_ERROR, zf, arg_num, "be of the type ", zend_get_type_by_const(cur_arg_info->type_hint), "none", "", NULL); + zend_verify_arg_error(zf, arg_num, "be of the type ", zend_get_type_by_const(cur_arg_info->type_hint), "none", "", NULL); } return 0; } @@ -850,7 +853,7 @@ static void zend_verify_missing_arg(zend_execute_data *execute_data, uint32_t ar } } -ZEND_API void zend_verify_return_error(int error_type, 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_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; @@ -864,8 +867,7 @@ ZEND_API void zend_verify_return_error(int error_type, const zend_function *zf, fclass = ""; } - zend_error(error_type, - "Return value of %s%s%s() must %s%s, %s%s returned", + 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); } @@ -882,30 +884,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(E_CORE_ERROR, zf, need_msg, class_name, "instance of ", Z_OBJCE_P(ret)->name->val); + zend_verify_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(E_CORE_ERROR, zf, need_msg, class_name, zend_zval_type_name(ret), ""); + zend_verify_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(E_CORE_ERROR, zf, "be of the type array", "", zend_zval_type_name(ret), ""); + zend_verify_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(E_CORE_ERROR, zf, "be callable", "", zend_zval_type_name(ret), ""); + zend_verify_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(E_EXCEPTION | E_ERROR, zf, "be of the type ", zend_get_type_by_const(ret_info->type_hint), zend_zval_type_name(ret), ""); + zend_verify_return_error(zf, "be of the type ", zend_get_type_by_const(ret_info->type_hint), zend_zval_type_name(ret), ""); } return 0; } @@ -930,26 +932,26 @@ static void zend_verify_return_type(zend_function *zf, zval *ret, zend_bool stri if (Z_TYPE_P(ret) == IS_OBJECT) { need_msg = zend_verify_arg_class_kind(ret_info, &class_name, &ce); if (!ce || !instanceof_function(Z_OBJCE_P(ret), ce)) { - zend_verify_return_error(E_EXCEPTION | E_ERROR, zf, need_msg, class_name, "instance of ", Z_OBJCE_P(ret)->name->val); + zend_verify_return_error(zf, need_msg, class_name, "instance of ", Z_OBJCE_P(ret)->name->val); } } else if (Z_TYPE_P(ret) != IS_NULL || !ret_info->allow_null) { need_msg = zend_verify_arg_class_kind(ret_info, &class_name, &ce); - zend_verify_return_error(E_EXCEPTION | E_ERROR, zf, need_msg, class_name, zend_zval_type_name(ret), ""); + zend_verify_return_error(zf, need_msg, class_name, zend_zval_type_name(ret), ""); } } 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(E_EXCEPTION | E_ERROR, zf, "be of the type array", "", zend_zval_type_name(ret), ""); + zend_verify_return_error(zf, "be of the type array", "", zend_zval_type_name(ret), ""); } } 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(E_EXCEPTION | E_ERROR, zf, "be callable", "", zend_zval_type_name(ret), ""); + zend_verify_return_error(zf, "be callable", "", zend_zval_type_name(ret), ""); } } 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(E_EXCEPTION | E_ERROR, zf, "be of the type ", zend_get_type_by_const(ret_info->type_hint), zend_zval_type_name(ret), ""); + zend_verify_return_error(zf, "be of the type ", zend_get_type_by_const(ret_info->type_hint), zend_zval_type_name(ret), ""); } return; } @@ -970,15 +972,15 @@ static inline int zend_verify_missing_return_type(zend_function *zf) char *class_name; need_msg = zend_verify_arg_class_kind(ret_info, &class_name, &ce); - zend_verify_return_error(E_EXCEPTION | E_ERROR, zf, need_msg, class_name, "none", ""); + zend_verify_return_error(zf, need_msg, class_name, "none", ""); return 0; } else if (ret_info->type_hint) { if (ret_info->type_hint == IS_ARRAY) { - zend_verify_return_error(E_EXCEPTION | E_ERROR, zf, "be of the type array", "", "none", ""); + zend_verify_return_error(zf, "be of the type array", "", "none", ""); } else if (ret_info->type_hint == IS_CALLABLE) { - zend_verify_return_error(E_EXCEPTION | E_ERROR, zf, "be callable", "", "none", ""); + zend_verify_return_error(zf, "be callable", "", "none", ""); } else { - zend_verify_return_error(E_EXCEPTION | E_ERROR, zf, "be of the type ", zend_get_type_by_const(ret_info->type_hint), "none", ""); + zend_verify_return_error(zf, "be of the type ", zend_get_type_by_const(ret_info->type_hint), "none", ""); } return 0; } diff --git a/Zend/zend_execute.h b/Zend/zend_execute.h index 0149da6929..c040c8f633 100644 --- a/Zend/zend_execute.h +++ b/Zend/zend_execute.h @@ -49,8 +49,8 @@ ZEND_API int zend_eval_stringl_ex(char *str, size_t str_len, zval *retval_ptr, c ZEND_API char * zend_verify_internal_arg_class_kind(const zend_internal_arg_info *cur_arg_info, char **class_name, zend_class_entry **pce); 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(int error_type, 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(int error_type, 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_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); static zend_always_inline zval* zend_assign_to_variable(zval *variable_ptr, zval *value, zend_uchar value_type) {