Skip to content

Commit dcaf62f

Browse files
committed
Clean up zend_check_magic_method_implementation
Let everything go through a common function, which fixes some consistency issues.
1 parent 9dc08f7 commit dcaf62f

File tree

3 files changed

+46
-44
lines changed

3 files changed

+46
-44
lines changed

Zend/tests/errmsg_015.phpt

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,4 +11,4 @@ class test {
1111
echo "Done\n";
1212
?>
1313
--EXPECTF--
14-
Fatal error: Method test::__clone() cannot accept any arguments in %s on line %d
14+
Fatal error: Method test::__clone() cannot take arguments in %s on line %d

Zend/tests/errmsg_019.phpt

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,4 +11,4 @@ class test {
1111
echo "Done\n";
1212
?>
1313
--EXPECTF--
14-
Fatal error: Destructor test::__destruct() cannot take arguments in %s on line %d
14+
Fatal error: Method test::__destruct() cannot take arguments in %s on line %d

Zend/zend_API.c

Lines changed: 44 additions & 42 deletions
Original file line numberDiff line numberDiff line change
@@ -2007,61 +2007,63 @@ ZEND_API zend_module_entry* zend_register_internal_module(zend_module_entry *mod
20072007
}
20082008
/* }}} */
20092009

2010+
static void zend_check_magic_method_args(
2011+
uint32_t num_args, const char *name,
2012+
const zend_class_entry *ce, const zend_function *fptr, int error_type)
2013+
{
2014+
if (fptr->common.num_args != num_args) {
2015+
if (num_args == 0) {
2016+
zend_error(error_type, "Method %s::%s() cannot take arguments",
2017+
ZSTR_VAL(ce->name), name);
2018+
} else if (num_args == 1) {
2019+
zend_error(error_type, "Method %s::%s() must take exactly 1 argument",
2020+
ZSTR_VAL(ce->name), name);
2021+
} else {
2022+
zend_error(error_type, "Method %s::%s() must take exactly %" PRIu32 " arguments",
2023+
ZSTR_VAL(ce->name), name, num_args);
2024+
}
2025+
return;
2026+
}
2027+
for (uint32_t i = 0; i < num_args; i++) {
2028+
if (QUICK_ARG_SHOULD_BE_SENT_BY_REF(fptr, i + 1)) {
2029+
zend_error(error_type, "Method %s::%s() cannot take arguments by reference",
2030+
ZSTR_VAL(ce->name), name);
2031+
return;
2032+
}
2033+
}
2034+
}
2035+
20102036
ZEND_API void zend_check_magic_method_implementation(const zend_class_entry *ce, const zend_function *fptr, zend_string *lcname, int error_type) /* {{{ */
20112037
{
20122038
if (ZSTR_VAL(fptr->common.function_name)[0] != '_'
20132039
|| ZSTR_VAL(fptr->common.function_name)[1] != '_') {
20142040
return;
20152041
}
20162042

2017-
if (zend_string_equals_literal(lcname, ZEND_DESTRUCTOR_FUNC_NAME) && fptr->common.num_args != 0) {
2018-
zend_error(error_type, "Destructor %s::%s() cannot take arguments", ZSTR_VAL(ce->name), ZEND_DESTRUCTOR_FUNC_NAME);
2019-
} else if (zend_string_equals_literal(lcname, ZEND_CLONE_FUNC_NAME) && fptr->common.num_args != 0) {
2020-
zend_error(error_type, "Method %s::%s() cannot accept any arguments", ZSTR_VAL(ce->name), ZEND_CLONE_FUNC_NAME);
2043+
if (zend_string_equals_literal(lcname, ZEND_DESTRUCTOR_FUNC_NAME)) {
2044+
zend_check_magic_method_args(0, "__destruct", ce, fptr, error_type);
2045+
} else if (zend_string_equals_literal(lcname, ZEND_CLONE_FUNC_NAME)) {
2046+
zend_check_magic_method_args(0, "__clone", ce, fptr, error_type);
20212047
} else if (zend_string_equals_literal(lcname, ZEND_GET_FUNC_NAME)) {
2022-
if (fptr->common.num_args != 1) {
2023-
zend_error(error_type, "Method %s::%s() must take exactly 1 argument", ZSTR_VAL(ce->name), ZEND_GET_FUNC_NAME);
2024-
} else if (QUICK_ARG_SHOULD_BE_SENT_BY_REF(fptr, 1)) {
2025-
zend_error(error_type, "Method %s::%s() cannot take arguments by reference", ZSTR_VAL(ce->name), ZEND_GET_FUNC_NAME);
2026-
}
2048+
zend_check_magic_method_args(1, "__get", ce, fptr, error_type);
20272049
} else if (zend_string_equals_literal(lcname, ZEND_SET_FUNC_NAME)) {
2028-
if (fptr->common.num_args != 2) {
2029-
zend_error(error_type, "Method %s::%s() must take exactly 2 arguments", ZSTR_VAL(ce->name), ZEND_SET_FUNC_NAME);
2030-
} else if (QUICK_ARG_SHOULD_BE_SENT_BY_REF(fptr, 1) || QUICK_ARG_SHOULD_BE_SENT_BY_REF(fptr, 2)) {
2031-
zend_error(error_type, "Method %s::%s() cannot take arguments by reference", ZSTR_VAL(ce->name), ZEND_SET_FUNC_NAME);
2032-
}
2050+
zend_check_magic_method_args(2, "__set", ce, fptr, error_type);
20332051
} else if (zend_string_equals_literal(lcname, ZEND_UNSET_FUNC_NAME)) {
2034-
if (fptr->common.num_args != 1) {
2035-
zend_error(error_type, "Method %s::%s() must take exactly 1 argument", ZSTR_VAL(ce->name), ZEND_UNSET_FUNC_NAME);
2036-
} else if (QUICK_ARG_SHOULD_BE_SENT_BY_REF(fptr, 1)) {
2037-
zend_error(error_type, "Method %s::%s() cannot take arguments by reference", ZSTR_VAL(ce->name), ZEND_UNSET_FUNC_NAME);
2038-
}
2052+
zend_check_magic_method_args(1, "__unset", ce, fptr, error_type);
20392053
} else if (zend_string_equals_literal(lcname, ZEND_ISSET_FUNC_NAME)) {
2040-
if (fptr->common.num_args != 1) {
2041-
zend_error(error_type, "Method %s::%s() must take exactly 1 argument", ZSTR_VAL(ce->name), ZEND_ISSET_FUNC_NAME);
2042-
} else if (QUICK_ARG_SHOULD_BE_SENT_BY_REF(fptr, 1)) {
2043-
zend_error(error_type, "Method %s::%s() cannot take arguments by reference", ZSTR_VAL(ce->name), ZEND_ISSET_FUNC_NAME);
2044-
}
2054+
zend_check_magic_method_args(1, "__isset", ce, fptr, error_type);
20452055
} else if (zend_string_equals_literal(lcname, ZEND_CALL_FUNC_NAME)) {
2046-
if (fptr->common.num_args != 2) {
2047-
zend_error(error_type, "Method %s::%s() must take exactly 2 arguments", ZSTR_VAL(ce->name), ZEND_CALL_FUNC_NAME);
2048-
} else if (QUICK_ARG_SHOULD_BE_SENT_BY_REF(fptr, 1) || QUICK_ARG_SHOULD_BE_SENT_BY_REF(fptr, 2)) {
2049-
zend_error(error_type, "Method %s::%s() cannot take arguments by reference", ZSTR_VAL(ce->name), ZEND_CALL_FUNC_NAME);
2050-
}
2056+
zend_check_magic_method_args(2, "__call", ce, fptr, error_type);
20512057
} else if (zend_string_equals_literal(lcname, ZEND_CALLSTATIC_FUNC_NAME)) {
2052-
if (fptr->common.num_args != 2) {
2053-
zend_error(error_type, "Method %s::__callStatic() must take exactly 2 arguments", ZSTR_VAL(ce->name));
2054-
} else if (QUICK_ARG_SHOULD_BE_SENT_BY_REF(fptr, 1) || QUICK_ARG_SHOULD_BE_SENT_BY_REF(fptr, 2)) {
2055-
zend_error(error_type, "Method %s::__callStatic() cannot take arguments by reference", ZSTR_VAL(ce->name));
2056-
}
2057-
} else if (zend_string_equals_literal(lcname, ZEND_TOSTRING_FUNC_NAME) && fptr->common.num_args != 0) {
2058-
zend_error(error_type, "Method %s::__toString() cannot take arguments", ZSTR_VAL(ce->name));
2059-
} else if (zend_string_equals_literal(lcname, ZEND_DEBUGINFO_FUNC_NAME) && fptr->common.num_args != 0) {
2060-
zend_error(error_type, "Method %s::__debugInfo() cannot take arguments", ZSTR_VAL(ce->name));
2061-
} else if (zend_string_equals_literal(lcname, "__serialize") && fptr->common.num_args != 0) {
2062-
zend_error(error_type, "Method %s::__serialize() cannot take arguments", ZSTR_VAL(ce->name));
2063-
} else if (zend_string_equals_literal(lcname, "__unserialize") && fptr->common.num_args != 1) {
2064-
zend_error(error_type, "Method %s::__unserialize() must take exactly 1 argument", ZSTR_VAL(ce->name));
2058+
zend_check_magic_method_args(2, "__callStatic", ce, fptr, error_type);
2059+
} else if (zend_string_equals_literal(lcname, ZEND_TOSTRING_FUNC_NAME)) {
2060+
zend_check_magic_method_args(0, "__toString", ce, fptr, error_type);
2061+
} else if (zend_string_equals_literal(lcname, ZEND_DEBUGINFO_FUNC_NAME)) {
2062+
zend_check_magic_method_args(0, "__debugInfo", ce, fptr, error_type);
2063+
} else if (zend_string_equals_literal(lcname, "__serialize")) {
2064+
zend_check_magic_method_args(0, "__serialize", ce, fptr, error_type);
2065+
} else if (zend_string_equals_literal(lcname, "__unserialize")) {
2066+
zend_check_magic_method_args(1, "__unserialize", ce, fptr, error_type);
20652067
}
20662068
}
20672069
/* }}} */

0 commit comments

Comments
 (0)