2 %sbug38047.php:36 kalus_error_handler()
-Fatal error: Uncaught Error: Too few arguments to function A::A_ftk(), 0 passed in %sbug38047.php on line 36 and exactly 1 expected in %sbug38047.php:7
+Fatal error: Uncaught ArgumentCountError: Too few arguments to function A::A_ftk(), 0 passed in %sbug38047.php on line 36 and exactly 1 expected in %sbug38047.php:7
Stack trace:
#0 %sbug38047.php(36): A::A_ftk()
#1 {main}
f();
?>
--EXPECTF--
-Fatal error: Uncaught Error: Too few arguments to function f(), 0 passed in %s on line 3 and exactly 1 expected in %s:2
+Fatal error: Uncaught ArgumentCountError: Too few arguments to function f(), 0 passed in %s on line 3 and exactly 1 expected in %s:2
Stack trace:
#0 %s(%d): f()
#1 {main}
?>
--EXPECTF--
-Fatal error: Uncaught Error: Too few arguments to function foo(), 0 passed in %sbug70689.php on line 12 and exactly 1 expected in %sbug70689.php:3
+Fatal error: Uncaught ArgumentCountError: Too few arguments to function foo(), 0 passed in %sbug70689.php on line 12 and exactly 1 expected in %sbug70689.php:3
Stack trace:
#0 %sbug70689.php(12): foo()
#1 {main}
--- /dev/null
+--TEST--
+Call function with correct number of arguments
+--FILE--
+<?php
+function foo() { }
+foo();
+
+function bar($foo, $bar) { }
+bar(1, 2);
+
+function bat(int $foo, string $bar) { }
+bat(123, "foo");
+bat("123", "foo");
+
+$fp = fopen(__FILE__, "r");
+fclose($fp);
+
+echo "done";
+--EXPECT--
+done
\ No newline at end of file
--- /dev/null
+--TEST--
+Call function with correct number of arguments with strict types
+--FILE--
+<?php
+declare(strict_types=1);
+function foo() { }
+foo();
+
+function bar($foo, $bar) { }
+bar(1, 2);
+
+function bat(int $foo, string $bar) { }
+bat(123, "foo");
+
+$fp = fopen(__FILE__, "r");
+fclose($fp);
+
+echo "done";
+--EXPECT--
+done
\ No newline at end of file
--- /dev/null
+--TEST--
+Call internal function with incorrect number of arguments
+--FILE--
+<?php
+substr("foo");
+array_diff([]);
+--EXPECTF--
+Warning: substr() expects at least 2 parameters, 1 given in %s
+
+Warning: array_diff(): at least 2 parameters are required, 1 given in %s
\ No newline at end of file
--- /dev/null
+--TEST--
+Call internal function with incorrect number of arguments with strict types
+--FILE--
+<?php
+declare(strict_types=1);
+try {
+ substr("foo");
+} catch (\Error $e) {
+ echo get_class($e) . PHP_EOL;
+ echo $e->getMessage() . PHP_EOL;
+}
+
+array_diff([]);
+--EXPECTF--
+ArgumentCountError
+substr() expects at least 2 parameters, 1 given
+
+Warning: array_diff(): at least 2 parameters are required, 1 given in %s
\ No newline at end of file
--- /dev/null
+--TEST--
+Call userland function with incorrect number of arguments
+--FILE--
+<?php
+try {
+ function foo($bar) { }
+ foo();
+} catch (\Error $e) {
+ echo get_class($e) . PHP_EOL;
+ echo $e->getMessage() . PHP_EOL;
+}
+
+try {
+ function bar($foo, $bar) { }
+ bar(1);
+} catch (\Error $e) {
+ echo get_class($e) . PHP_EOL;
+ echo $e->getMessage() . PHP_EOL;
+}
+
+function bat(int $foo, string $bar) { }
+
+try {
+ bat(123);
+} catch (\Error $e) {
+ echo get_class($e) . PHP_EOL;
+ echo $e->getMessage() . PHP_EOL;
+}
+
+try {
+ bat("123");
+} catch (\Error $e) {
+ echo get_class($e) . PHP_EOL;
+ echo $e->getMessage() . PHP_EOL;
+}
+--EXPECTF--
+ArgumentCountError
+Too few arguments to function foo(), 0 passed in %s and exactly 1 expected
+ArgumentCountError
+Too few arguments to function bar(), 1 passed in %s and exactly 2 expected
+ArgumentCountError
+Too few arguments to function bat(), 1 passed in %s and exactly 2 expected
+ArgumentCountError
+Too few arguments to function bat(), 1 passed in %s and exactly 2 expected
\ No newline at end of file
--- /dev/null
+--TEST--
+Call userland function with incorrect number of arguments with strict types
+--FILE--
+<?php
+declare(strict_types=1);
+try {
+ function foo($bar) { }
+ foo();
+} catch (\Error $e) {
+ echo get_class($e) . PHP_EOL;
+ echo $e->getMessage() . PHP_EOL;
+}
+
+try {
+ function bar($foo, $bar) { }
+ bar(1);
+} catch (\Error $e) {
+ echo get_class($e) . PHP_EOL;
+ echo $e->getMessage() . PHP_EOL;
+}
+
+function bat(int $foo, string $bar) { }
+
+try {
+ bat(123);
+} catch (\Error $e) {
+ echo get_class($e) . PHP_EOL;
+ echo $e->getMessage() . PHP_EOL;
+}
+
+try {
+ bat("123");
+} catch (\Error $e) {
+ echo get_class($e) . PHP_EOL;
+ echo $e->getMessage() . PHP_EOL;
+}
+
+try {
+ bat(123, 456);
+} catch (\Error $e) {
+ echo get_class($e) . PHP_EOL;
+ echo $e->getMessage() . PHP_EOL;
+}
+--EXPECTF--
+ArgumentCountError
+Too few arguments to function foo(), 0 passed in %s and exactly 1 expected
+ArgumentCountError
+Too few arguments to function bar(), 1 passed in %s and exactly 2 expected
+ArgumentCountError
+Too few arguments to function bat(), 1 passed in %s and exactly 2 expected
+TypeError
+Argument 1 passed to bat() must be of the type integer, string given, called in %s
+TypeError
+Argument 2 passed to bat() must be of the type string, integer given, called in %s
\ No newline at end of file
f();
--EXPECTF--
-Fatal error: Uncaught Error: Too few arguments to function f(), 0 passed in %snullable_type_parameters_do_not_have_default_value.php on line %d and exactly 1 expected in %s:%d
+Fatal error: Uncaught ArgumentCountError: Too few arguments to function f(), 0 passed in %snullable_type_parameters_do_not_have_default_value.php on line %d and exactly 1 expected in %s:%d
Stack trace:
#%d %s
#%d %s
va_end(va);
} /* }}} */
+ZEND_API ZEND_COLD void zend_internal_argument_count_error(zend_bool throw_exception, const char *format, ...) /* {{{ */
+{
+ va_list va;
+ char *message = NULL;
+
+ va_start(va, format);
+ zend_vspprintf(&message, 0, format, va);
+ if (throw_exception) {
+ zend_throw_exception(zend_ce_argument_count_error, message, 0);
+ } else {
+ zend_error(E_WARNING, "%s", message);
+ }
+ efree(message);
+
+ va_end(va);
+} /* }}} */
+
ZEND_API ZEND_COLD void zend_output_debug_string(zend_bool trigger_break, const char *format, ...) /* {{{ */
{
#if ZEND_DEBUG
ZEND_API ZEND_COLD void zend_throw_error(zend_class_entry *exception_ce, const char *format, ...) ZEND_ATTRIBUTE_FORMAT(printf, 2, 3);
ZEND_API ZEND_COLD void zend_type_error(const char *format, ...) ZEND_ATTRIBUTE_FORMAT(printf, 1, 2);
ZEND_API ZEND_COLD void zend_internal_type_error(zend_bool throw_exception, const char *format, ...) ZEND_ATTRIBUTE_FORMAT(printf, 2, 3);
+ZEND_API ZEND_COLD void zend_internal_argument_count_error(zend_bool throw_exception, const char *format, ...) ZEND_ATTRIBUTE_FORMAT(printf, 2, 3);
ZEND_COLD void zenderror(const char *error);
const char *space;
const char *class_name = get_active_class_name(&space);
- zend_internal_type_error(ZEND_ARG_USES_STRICT_TYPES(), "Wrong parameter count for %s%s%s()", class_name, space, get_active_function_name());
+ zend_internal_argument_count_error(ZEND_ARG_USES_STRICT_TYPES(), "Wrong parameter count for %s%s%s()", class_name, space, get_active_function_name());
}
/* }}} */
zend_function *active_function = EG(current_execute_data)->func;
const char *class_name = active_function->common.scope ? ZSTR_VAL(active_function->common.scope->name) : "";
- zend_internal_type_error(ZEND_ARG_USES_STRICT_TYPES(), "%s%s%s() expects %s %d parameter%s, %d given",
- class_name, \
- class_name[0] ? "::" : "", \
- ZSTR_VAL(active_function->common.function_name),
- min_num_args == max_num_args ? "exactly" : num_args < min_num_args ? "at least" : "at most",
- num_args < min_num_args ? min_num_args : max_num_args,
- (num_args < min_num_args ? min_num_args : max_num_args) == 1 ? "" : "s",
- num_args);
+ zend_internal_argument_count_error(
+ ZEND_ARG_USES_STRICT_TYPES(),
+ "%s%s%s() expects %s %d parameter%s, %d given",
+ class_name, \
+ class_name[0] ? "::" : "", \
+ ZSTR_VAL(active_function->common.function_name),
+ min_num_args == max_num_args ? "exactly" : num_args < min_num_args ? "at least" : "at most",
+ num_args < min_num_args ? min_num_args : max_num_args,
+ (num_args < min_num_args ? min_num_args : max_num_args) == 1 ? "" : "s",
+ num_args);
}
/* }}} */
zend_function *active_function = EG(current_execute_data)->func;
const char *class_name = active_function->common.scope ? ZSTR_VAL(active_function->common.scope->name) : "";
zend_bool throw_exception = ZEND_ARG_USES_STRICT_TYPES() || (flags & ZEND_PARSE_PARAMS_THROW);
- zend_internal_type_error(throw_exception, "%s%s%s() expects %s %d parameter%s, %d given",
+ zend_internal_argument_count_error(throw_exception, "%s%s%s() expects %s %d parameter%s, %d given",
class_name,
class_name[0] ? "::" : "",
ZSTR_VAL(active_function->common.function_name),
ZEND_API zend_class_entry *zend_ce_error;
ZEND_API zend_class_entry *zend_ce_parse_error;
ZEND_API zend_class_entry *zend_ce_type_error;
+ZEND_API zend_class_entry *zend_ce_argument_count_error;
ZEND_API zend_class_entry *zend_ce_arithmetic_error;
ZEND_API zend_class_entry *zend_ce_division_by_zero_error;
ZVAL_UNDEF(&trace);
}
- if (Z_OBJCE_P(exception) == zend_ce_type_error && strstr(ZSTR_VAL(message), ", called in ")) {
+ if ((Z_OBJCE_P(exception) == zend_ce_type_error || Z_OBJCE_P(exception) == zend_ce_argument_count_error) && strstr(ZSTR_VAL(message), ", called in ")) {
zend_string *real_message = zend_strpprintf(0, "%s and defined", ZSTR_VAL(message));
zend_string_release(message);
message = real_message;
zend_ce_type_error = zend_register_internal_class_ex(&ce, zend_ce_error);
zend_ce_type_error->create_object = zend_default_exception_new;
+ INIT_CLASS_ENTRY(ce, "ArgumentCountError", NULL);
+ zend_ce_argument_count_error = zend_register_internal_class_ex(&ce, zend_ce_type_error);
+ zend_ce_argument_count_error->create_object = zend_default_exception_new;
+
INIT_CLASS_ENTRY(ce, "ArithmeticError", NULL);
zend_ce_arithmetic_error = zend_register_internal_class_ex(&ce, zend_ce_error);
zend_ce_arithmetic_error->create_object = zend_default_exception_new;
extern ZEND_API zend_class_entry *zend_ce_error;
extern ZEND_API zend_class_entry *zend_ce_parse_error;
extern ZEND_API zend_class_entry *zend_ce_type_error;
+extern ZEND_API zend_class_entry *zend_ce_argument_count_error;
extern ZEND_API zend_class_entry *zend_ce_arithmetic_error;
extern ZEND_API zend_class_entry *zend_ce_division_by_zero_error;
const char *fname, *fsep, *fclass;
const char *need_msg, *need_kind, *need_or_null, *given_msg, *given_kind;
- zend_verify_type_error_common(
- zf, arg_info, ce, value,
- &fname, &fsep, &fclass, &need_msg, &need_kind, &need_or_null, &given_msg, &given_kind);
-
- if (zf->common.type == ZEND_USER_FUNCTION) {
- if (ptr && ptr->func && ZEND_USER_CODE(ptr->func->common.type)) {
- zend_type_error("Argument %d passed to %s%s%s() must %s%s%s, %s%s given, called in %s on line %d",
- arg_num, fclass, fsep, fname, need_msg, need_kind, need_or_null, given_msg, given_kind,
- ZSTR_VAL(ptr->func->op_array.filename), ptr->opline->lineno);
+ if (value) {
+ zend_verify_type_error_common(
+ zf, arg_info, ce, value,
+ &fname, &fsep, &fclass, &need_msg, &need_kind, &need_or_null, &given_msg, &given_kind);
+
+ if (zf->common.type == ZEND_USER_FUNCTION) {
+ if (ptr && ptr->func && ZEND_USER_CODE(ptr->func->common.type)) {
+ zend_type_error("Argument %d passed to %s%s%s() must %s%s%s, %s%s given, called in %s on line %d",
+ arg_num, fclass, fsep, fname, need_msg, need_kind, need_or_null, given_msg, given_kind,
+ ZSTR_VAL(ptr->func->op_array.filename), ptr->opline->lineno);
+ } else {
+ zend_type_error("Argument %d passed to %s%s%s() must %s%s%s, %s%s given", arg_num, fclass, fsep, fname, need_msg, need_kind, need_or_null, given_msg, given_kind);
+ }
} else {
zend_type_error("Argument %d passed to %s%s%s() must %s%s%s, %s%s given", arg_num, fclass, fsep, fname, need_msg, need_kind, need_or_null, given_msg, given_kind);
}
} else {
- zend_type_error("Argument %d passed to %s%s%s() must %s%s%s, %s%s given", arg_num, fclass, fsep, fname, need_msg, need_kind, need_or_null, given_msg, given_kind);
+ zend_missing_arg_error(ptr);
}
}
zend_execute_data *ptr = EX(prev_execute_data);
if (ptr && ptr->func && ZEND_USER_CODE(ptr->func->common.type)) {
- zend_throw_error(NULL, "Too few arguments to function %s%s%s(), %d passed in %s on line %d and %s %d expected",
+ zend_throw_error(zend_ce_argument_count_error, "Too few arguments to function %s%s%s(), %d passed in %s on line %d and %s %d expected",
EX(func)->common.scope ? ZSTR_VAL(EX(func)->common.scope->name) : "",
EX(func)->common.scope ? "::" : "",
ZSTR_VAL(EX(func)->common.function_name),
EX(func)->common.required_num_args == EX(func)->common.num_args ? "exactly" : "at least",
EX(func)->common.required_num_args);
} else {
- zend_throw_error(NULL, "Too few arguments to function %s%s%s(), %d passed and %s %d expected",
+ zend_throw_error(zend_ce_argument_count_error, "Too few arguments to function %s%s%s(), %d passed and %s %d expected",
EX(func)->common.scope ? ZSTR_VAL(EX(func)->common.scope->name) : "",
EX(func)->common.scope ? "::" : "",
ZSTR_VAL(EX(func)->common.function_name),
--EXPECTF--
Method with args:
-Fatal error: Uncaught Error: Too few arguments to function TestClass::methodWithArgs(), 0 passed and exactly 2 expected in %sReflectionMethod_invokeArgs_error1.php:5
+Fatal error: Uncaught ArgumentCountError: Too few arguments to function TestClass::methodWithArgs(), 0 passed and exactly 2 expected in %sReflectionMethod_invokeArgs_error1.php:5
Stack trace:
#0 [internal function]: TestClass->methodWithArgs()
#1 %sReflectionMethod_invokeArgs_error1.php(19): ReflectionMethod->invokeArgs(Object(TestClass), Array)
--EXPECTF--
Method with args:
-Fatal error: Uncaught Error: Too few arguments to function TestClass::methodWithArgs(), 0 passed and exactly 2 expected in %sReflectionMethod_invoke_error2.php:5
+Fatal error: Uncaught ArgumentCountError: Too few arguments to function TestClass::methodWithArgs(), 0 passed and exactly 2 expected in %sReflectionMethod_invoke_error2.php:5
Stack trace:
#0 [internal function]: TestClass->methodWithArgs()
#1 %sReflectionMethod_invoke_error2.php(15): ReflectionMethod->invoke(Object(TestClass))
Warning: assert(): Assertion "0 != 0" failed in %s on line 9
-Fatal error: Uncaught Error: Too few arguments to function f1(), 3 passed and exactly 4 expected in %sassert_error2.php:2
+Fatal error: Uncaught ArgumentCountError: Too few arguments to function f1(), 3 passed and exactly 4 expected in %sassert_error2.php:2
Stack trace:
#0 [internal function]: f1('%s', 9, '0 != 0')
#1 %sassert_error2.php(9): assert('0 != 0')
--EXPECTF--
Warning: fopen(var://myvar): failed to open stream: "VariableStream::stream_open" call failed in %sbug38450_3.php on line %d
-Fatal error: Uncaught Error: Too few arguments to function VariableStream::__construct(), 0 passed and exactly 1 expected in %sbug38450_3.php:7
+Fatal error: Uncaught ArgumentCountError: Too few arguments to function VariableStream::__construct(), 0 passed and exactly 1 expected in %sbug38450_3.php:7
Stack trace:
#0 [internal function]: VariableStream->__construct()
#1 %s(%d): fopen('var://myvar', 'r+')
===DONE===
--EXPECTF--
-Fatal error: Uncaught Error: Too few arguments to function MyTestClass::__construct(), 0 passed in %sinterfaces_003.php on line 17 and exactly 1 expected in %sinterfaces_003.php:12
+Fatal error: Uncaught ArgumentCountError: Too few arguments to function MyTestClass::__construct(), 0 passed in %sinterfaces_003.php on line 17 and exactly 1 expected in %sinterfaces_003.php:12
Stack trace:
#0 %s(%d): MyTestClass->__construct()
#1 {main}