]> granicus.if.org Git - php/commitdiff
MFH: prohibit arguments by ref in magic methods
authorAntony Dovgal <tony2001@php.net>
Fri, 31 Aug 2007 12:36:14 +0000 (12:36 +0000)
committerAntony Dovgal <tony2001@php.net>
Fri, 31 Aug 2007 12:36:14 +0000 (12:36 +0000)
Zend/tests/magic_by_ref_001.phpt [new file with mode: 0644]
Zend/tests/magic_by_ref_002.phpt [new file with mode: 0644]
Zend/tests/magic_by_ref_003.phpt [new file with mode: 0644]
Zend/tests/magic_by_ref_004.phpt [new file with mode: 0644]
Zend/tests/magic_by_ref_005.phpt [new file with mode: 0644]
Zend/tests/magic_by_ref_006.phpt [new file with mode: 0644]
Zend/tests/magic_by_ref_007.phpt [new file with mode: 0644]
Zend/tests/magic_by_ref_010.phpt [new file with mode: 0644]
Zend/zend_API.c

diff --git a/Zend/tests/magic_by_ref_001.phpt b/Zend/tests/magic_by_ref_001.phpt
new file mode 100644 (file)
index 0000000..e9bcf8f
--- /dev/null
@@ -0,0 +1,17 @@
+--TEST--
+passing first parameter of __set() by ref
+--FILE--
+<?php
+
+class test {
+    function __set(&$name, $val) { }
+}
+
+$t = new test;
+$name = "prop";
+$t->$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 (file)
index 0000000..cb62f67
--- /dev/null
@@ -0,0 +1,16 @@
+--TEST--
+passing second parameter of __set() by ref
+--FILE--
+<?php
+
+class test {
+    function __set($name, &$val) { }
+}
+
+$t = new test;
+$t->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 (file)
index 0000000..022cbd5
--- /dev/null
@@ -0,0 +1,17 @@
+--TEST--
+passing parameter of __get() by ref
+--FILE--
+<?php
+
+class test {
+    function __get(&$name) { }
+}
+
+$t = new test;
+$name = "prop";
+var_dump($t->$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 (file)
index 0000000..aa04d1a
--- /dev/null
@@ -0,0 +1,18 @@
+--TEST--
+passing parameter of __unset() by ref
+--FILE--
+<?php
+
+class test {
+    function __unset(&$name) { }
+}
+
+$t = new test;
+$name = "prop";
+
+var_dump($t->$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 (file)
index 0000000..513c061
--- /dev/null
@@ -0,0 +1,18 @@
+--TEST--
+passing parameter of __isset() by ref
+--FILE--
+<?php
+
+class test {
+    function __isset(&$name) { }
+}
+
+$t = new test;
+$name = "prop";
+
+var_dump(isset($t->$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 (file)
index 0000000..14d7d70
--- /dev/null
@@ -0,0 +1,18 @@
+--TEST--
+passing first parameter of __call() by ref
+--FILE--
+<?php
+
+class test {
+    function __call(&$name, $args) { }
+}
+
+$t = new test;
+$func = "foo";
+
+$t->$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 (file)
index 0000000..c962d45
--- /dev/null
@@ -0,0 +1,19 @@
+--TEST--
+passing second parameter of __call() by ref
+--FILE--
+<?php
+
+class test {
+    function __call($name, &$args) { }
+}
+
+$t = new test;
+$func = "foo";
+$arg = 1;
+
+$t->$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 (file)
index 0000000..48f2353
--- /dev/null
@@ -0,0 +1,28 @@
+--TEST--
+passing arguments by ref to a method handled by __call()
+--FILE--
+<?php
+
+class Foo {
+    function __call($method, $args)
+    {
+        print $args[0]."\n";
+        $args[0] = 5;
+        print $args[0]."\n";
+        return true;
+    }
+}
+
+$v = 'str';
+$o = new Foo();
+$o->test(&$v);
+
+var_dump($v);
+
+echo "Done\n";
+?>
+--EXPECTF--    
+str
+5
+int(5)
+Done
index 5092e8ca72983cbabd5d10a82a7691e5fc11f23f..1d9f9b29175c84fafe61c3e33087e9dc18ffc985 100644 (file)
@@ -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);
+               }
        }
 }