From 90d58d466880e16df63d0ebe00b4c4db60b01184 Mon Sep 17 00:00:00 2001 From: Antony Dovgal Date: Fri, 31 Aug 2007 12:36:14 +0000 Subject: [PATCH] MFH: prohibit arguments by ref in magic methods --- Zend/tests/magic_by_ref_001.phpt | 17 ++++++++++++++ Zend/tests/magic_by_ref_002.phpt | 16 +++++++++++++ Zend/tests/magic_by_ref_003.phpt | 17 ++++++++++++++ Zend/tests/magic_by_ref_004.phpt | 18 ++++++++++++++ Zend/tests/magic_by_ref_005.phpt | 18 ++++++++++++++ Zend/tests/magic_by_ref_006.phpt | 18 ++++++++++++++ Zend/tests/magic_by_ref_007.phpt | 19 +++++++++++++++ Zend/tests/magic_by_ref_010.phpt | 28 ++++++++++++++++++++++ Zend/zend_API.c | 40 ++++++++++++++++++++++++-------- 9 files changed, 181 insertions(+), 10 deletions(-) create mode 100644 Zend/tests/magic_by_ref_001.phpt create mode 100644 Zend/tests/magic_by_ref_002.phpt create mode 100644 Zend/tests/magic_by_ref_003.phpt create mode 100644 Zend/tests/magic_by_ref_004.phpt create mode 100644 Zend/tests/magic_by_ref_005.phpt create mode 100644 Zend/tests/magic_by_ref_006.phpt create mode 100644 Zend/tests/magic_by_ref_007.phpt create mode 100644 Zend/tests/magic_by_ref_010.phpt diff --git a/Zend/tests/magic_by_ref_001.phpt b/Zend/tests/magic_by_ref_001.phpt new file mode 100644 index 0000000000..e9bcf8fa28 --- /dev/null +++ b/Zend/tests/magic_by_ref_001.phpt @@ -0,0 +1,17 @@ +--TEST-- +passing first parameter of __set() by ref +--FILE-- +$name = 1; + +echo "Done\n"; +?> +--EXPECTF-- +Fatal error: Method test::__set() cannot take arguments by reference in %s on line %d diff --git a/Zend/tests/magic_by_ref_002.phpt b/Zend/tests/magic_by_ref_002.phpt new file mode 100644 index 0000000000..cb62f67f56 --- /dev/null +++ b/Zend/tests/magic_by_ref_002.phpt @@ -0,0 +1,16 @@ +--TEST-- +passing second parameter of __set() by ref +--FILE-- +prop = 1; + +echo "Done\n"; +?> +--EXPECTF-- +Fatal error: Method test::__set() cannot take arguments by reference in %s on line %d diff --git a/Zend/tests/magic_by_ref_003.phpt b/Zend/tests/magic_by_ref_003.phpt new file mode 100644 index 0000000000..022cbd563c --- /dev/null +++ b/Zend/tests/magic_by_ref_003.phpt @@ -0,0 +1,17 @@ +--TEST-- +passing parameter of __get() by ref +--FILE-- +$name); + +echo "Done\n"; +?> +--EXPECTF-- +Fatal error: Method test::__get() cannot take arguments by reference in %s on line %d diff --git a/Zend/tests/magic_by_ref_004.phpt b/Zend/tests/magic_by_ref_004.phpt new file mode 100644 index 0000000000..aa04d1aee6 --- /dev/null +++ b/Zend/tests/magic_by_ref_004.phpt @@ -0,0 +1,18 @@ +--TEST-- +passing parameter of __unset() by ref +--FILE-- +$name); + +echo "Done\n"; +?> +--EXPECTF-- +Fatal error: Method test::__unset() cannot take arguments by reference in %s on line %d diff --git a/Zend/tests/magic_by_ref_005.phpt b/Zend/tests/magic_by_ref_005.phpt new file mode 100644 index 0000000000..513c0618df --- /dev/null +++ b/Zend/tests/magic_by_ref_005.phpt @@ -0,0 +1,18 @@ +--TEST-- +passing parameter of __isset() by ref +--FILE-- +$name)); + +echo "Done\n"; +?> +--EXPECTF-- +Fatal error: Method test::__isset() cannot take arguments by reference in %s on line %d diff --git a/Zend/tests/magic_by_ref_006.phpt b/Zend/tests/magic_by_ref_006.phpt new file mode 100644 index 0000000000..14d7d708b8 --- /dev/null +++ b/Zend/tests/magic_by_ref_006.phpt @@ -0,0 +1,18 @@ +--TEST-- +passing first parameter of __call() by ref +--FILE-- +$func(); + +echo "Done\n"; +?> +--EXPECTF-- +Fatal error: Method test::__call() cannot take arguments by reference in %s on line %d diff --git a/Zend/tests/magic_by_ref_007.phpt b/Zend/tests/magic_by_ref_007.phpt new file mode 100644 index 0000000000..c962d45813 --- /dev/null +++ b/Zend/tests/magic_by_ref_007.phpt @@ -0,0 +1,19 @@ +--TEST-- +passing second parameter of __call() by ref +--FILE-- +$func($arg); + +echo "Done\n"; +?> +--EXPECTF-- +Fatal error: Method test::__call() cannot take arguments by reference in %s on line %d diff --git a/Zend/tests/magic_by_ref_010.phpt b/Zend/tests/magic_by_ref_010.phpt new file mode 100644 index 0000000000..48f235355c --- /dev/null +++ b/Zend/tests/magic_by_ref_010.phpt @@ -0,0 +1,28 @@ +--TEST-- +passing arguments by ref to a method handled by __call() +--FILE-- +test(&$v); + +var_dump($v); + +echo "Done\n"; +?> +--EXPECTF-- +str +5 +int(5) +Done diff --git a/Zend/zend_API.c b/Zend/zend_API.c index 5092e8ca72..1d9f9b2917 100644 --- a/Zend/zend_API.c +++ b/Zend/zend_API.c @@ -1593,16 +1593,36 @@ ZEND_API void zend_check_magic_method_implementation(zend_class_entry *ce, zend_ zend_error(error_type, "Destructor %s::%s() cannot take arguments", ce->name, ZEND_DESTRUCTOR_FUNC_NAME); } else if (name_len == sizeof(ZEND_CLONE_FUNC_NAME) - 1 && !memcmp(lcname, ZEND_CLONE_FUNC_NAME, sizeof(ZEND_CLONE_FUNC_NAME)) && fptr->common.num_args != 0) { zend_error(error_type, "Method %s::%s() cannot accept any arguments", ce->name, ZEND_CLONE_FUNC_NAME); - } else if (name_len == sizeof(ZEND_GET_FUNC_NAME) - 1 && !memcmp(lcname, ZEND_GET_FUNC_NAME, sizeof(ZEND_GET_FUNC_NAME)) && fptr->common.num_args != 1) { - zend_error(error_type, "Method %s::%s() must take exactly 1 argument", ce->name, ZEND_GET_FUNC_NAME); - } else if (name_len == sizeof(ZEND_SET_FUNC_NAME) - 1 && !memcmp(lcname, ZEND_SET_FUNC_NAME, sizeof(ZEND_SET_FUNC_NAME)) && fptr->common.num_args != 2) { - zend_error(error_type, "Method %s::%s() must take exactly 2 arguments", ce->name, ZEND_SET_FUNC_NAME); - } else if (name_len == sizeof(ZEND_UNSET_FUNC_NAME) - 1 && !memcmp(lcname, ZEND_UNSET_FUNC_NAME, sizeof(ZEND_UNSET_FUNC_NAME)) && fptr->common.num_args != 1) { - zend_error(error_type, "Method %s::%s() must take exactly 1 argument", ce->name, ZEND_UNSET_FUNC_NAME); - } else if (name_len == sizeof(ZEND_ISSET_FUNC_NAME) - 1 && !memcmp(lcname, ZEND_ISSET_FUNC_NAME, sizeof(ZEND_ISSET_FUNC_NAME)) && fptr->common.num_args != 1) { - zend_error(error_type, "Method %s::%s() must take exactly 1 argument", ce->name, ZEND_ISSET_FUNC_NAME); - } else if (name_len == sizeof(ZEND_CALL_FUNC_NAME) - 1 && !memcmp(lcname, ZEND_CALL_FUNC_NAME, sizeof(ZEND_CALL_FUNC_NAME)) && fptr->common.num_args != 2) { - zend_error(error_type, "Method %s::%s() must take exactly 2 arguments", ce->name, ZEND_CALL_FUNC_NAME); + } else if (name_len == sizeof(ZEND_GET_FUNC_NAME) - 1 && !memcmp(lcname, ZEND_GET_FUNC_NAME, sizeof(ZEND_GET_FUNC_NAME))) { + if (fptr->common.num_args != 1) { + zend_error(error_type, "Method %s::%s() must take exactly 1 argument", ce->name, ZEND_GET_FUNC_NAME); + } else if (ARG_SHOULD_BE_SENT_BY_REF(fptr, 1)) { + zend_error(error_type, "Method %s::%s() cannot take arguments by reference", ce->name, ZEND_GET_FUNC_NAME); + } + } else if (name_len == sizeof(ZEND_SET_FUNC_NAME) - 1 && !memcmp(lcname, ZEND_SET_FUNC_NAME, sizeof(ZEND_SET_FUNC_NAME))) { + if (fptr->common.num_args != 2) { + zend_error(error_type, "Method %s::%s() must take exactly 2 arguments", ce->name, ZEND_SET_FUNC_NAME); + } else if (ARG_SHOULD_BE_SENT_BY_REF(fptr, 1) || ARG_SHOULD_BE_SENT_BY_REF(fptr, 2)) { + zend_error(error_type, "Method %s::%s() cannot take arguments by reference", ce->name, ZEND_SET_FUNC_NAME); + } + } else if (name_len == sizeof(ZEND_UNSET_FUNC_NAME) - 1 && !memcmp(lcname, ZEND_UNSET_FUNC_NAME, sizeof(ZEND_UNSET_FUNC_NAME))) { + if (fptr->common.num_args != 1) { + zend_error(error_type, "Method %s::%s() must take exactly 1 argument", ce->name, ZEND_UNSET_FUNC_NAME); + } else if (ARG_SHOULD_BE_SENT_BY_REF(fptr, 1)) { + zend_error(error_type, "Method %s::%s() cannot take arguments by reference", ce->name, ZEND_UNSET_FUNC_NAME); + } + } else if (name_len == sizeof(ZEND_ISSET_FUNC_NAME) - 1 && !memcmp(lcname, ZEND_ISSET_FUNC_NAME, sizeof(ZEND_ISSET_FUNC_NAME))) { + if (fptr->common.num_args != 1) { + zend_error(error_type, "Method %s::%s() must take exactly 1 argument", ce->name, ZEND_ISSET_FUNC_NAME); + } else if (ARG_SHOULD_BE_SENT_BY_REF(fptr, 1)) { + zend_error(error_type, "Method %s::%s() cannot take arguments by reference", ce->name, ZEND_ISSET_FUNC_NAME); + } + } else if (name_len == sizeof(ZEND_CALL_FUNC_NAME) - 1 && !memcmp(lcname, ZEND_CALL_FUNC_NAME, sizeof(ZEND_CALL_FUNC_NAME))) { + if (fptr->common.num_args != 2) { + zend_error(error_type, "Method %s::%s() must take exactly 2 arguments", ce->name, ZEND_CALL_FUNC_NAME); + } else if (ARG_SHOULD_BE_SENT_BY_REF(fptr, 1) || ARG_SHOULD_BE_SENT_BY_REF(fptr, 2)) { + zend_error(error_type, "Method %s::%s() cannot take arguments by reference", ce->name, ZEND_CALL_FUNC_NAME); + } } } -- 2.50.1