]> granicus.if.org Git - php/commitdiff
- Fixed bug #44769 (declaring private magic methods should throw error)
authorFelipe Pena <felipe@php.net>
Tue, 3 Jun 2008 13:55:47 +0000 (13:55 +0000)
committerFelipe Pena <felipe@php.net>
Tue, 3 Jun 2008 13:55:47 +0000 (13:55 +0000)
12 files changed:
Zend/tests/magic_methods_001.phpt [new file with mode: 0644]
Zend/tests/magic_methods_002.phpt [new file with mode: 0644]
Zend/tests/magic_methods_003.phpt [new file with mode: 0644]
Zend/tests/magic_methods_004.phpt [new file with mode: 0644]
Zend/tests/magic_methods_005.phpt [new file with mode: 0644]
Zend/tests/magic_methods_006.phpt [new file with mode: 0644]
Zend/tests/magic_methods_007.phpt [new file with mode: 0644]
Zend/tests/magic_methods_008.phpt [new file with mode: 0644]
Zend/tests/magic_methods_009.phpt [new file with mode: 0644]
Zend/tests/magic_methods_010.phpt [new file with mode: 0644]
Zend/zend_compile.c
tests/classes/__call_005.phpt

diff --git a/Zend/tests/magic_methods_001.phpt b/Zend/tests/magic_methods_001.phpt
new file mode 100644 (file)
index 0000000..8b1ddb3
--- /dev/null
@@ -0,0 +1,49 @@
+--TEST--
+Testing several magic methods
+--FILE--
+<?php
+
+class foo {    
+       function __unset($a) {
+               print "unset\n";
+               var_dump($a);
+       }
+       
+       public function __call($a, $b) {
+               print "call\n";
+               var_dump($a);
+       }
+       function __clone() {
+               print "clone\n";
+       }
+       static public function __callstatic($a, $b) {
+               print "callstatic\n";
+       }
+       
+       public function __tostring() {
+               return 'foo';
+       }
+}
+
+
+$a = new foo;
+
+$a->sdfdsa();
+
+$a::test();
+
+clone $a;
+
+var_dump((string)$a);
+
+unset($a->a);
+
+?>
+--EXPECT--
+call
+unicode(6) "sdfdsa"
+callstatic
+clone
+unicode(3) "foo"
+unset
+unicode(1) "a"
diff --git a/Zend/tests/magic_methods_002.phpt b/Zend/tests/magic_methods_002.phpt
new file mode 100644 (file)
index 0000000..da29aaa
--- /dev/null
@@ -0,0 +1,14 @@
+--TEST--
+Testing __unset with private visibility
+--FILE--
+<?php
+
+class foo {    
+       private function __unset($a) {
+               print "unset\n";
+       }
+}
+
+?>
+--EXPECTF--
+Fatal error: The magic method __unset() must have public visibility and can not be static in %s on line %d
diff --git a/Zend/tests/magic_methods_003.phpt b/Zend/tests/magic_methods_003.phpt
new file mode 100644 (file)
index 0000000..2580222
--- /dev/null
@@ -0,0 +1,14 @@
+--TEST--
+Testing __unset declaring as static
+--FILE--
+<?php
+
+class foo {    
+       static function __unset($a) {
+               print "unset\n";
+       }
+}
+
+?>
+--EXPECTF--
+Fatal error: The magic method __unset() must have public visibility and can not be static in %s on line %d
diff --git a/Zend/tests/magic_methods_004.phpt b/Zend/tests/magic_methods_004.phpt
new file mode 100644 (file)
index 0000000..c75e454
--- /dev/null
@@ -0,0 +1,14 @@
+--TEST--
+Testing __unset() with protected visibility
+--FILE--
+<?php
+
+class foo {    
+       protected function __unset($a) {
+               print "unset\n";
+       }
+}
+
+?>
+--EXPECTF--
+Fatal error: The magic method __unset() must have public visibility and can not be static in %s on line %d
diff --git a/Zend/tests/magic_methods_005.phpt b/Zend/tests/magic_methods_005.phpt
new file mode 100644 (file)
index 0000000..2cf84dc
--- /dev/null
@@ -0,0 +1,12 @@
+--TEST--
+Testing __call() declaration in interface with wrong modifier
+--FILE--
+<?php
+
+interface a {
+       static function __call($a, $b);
+}
+
+?>
+--EXPECTF--
+Fatal error: The magic method __call() must have public visibility and can not be static in %s on line %d
diff --git a/Zend/tests/magic_methods_006.phpt b/Zend/tests/magic_methods_006.phpt
new file mode 100644 (file)
index 0000000..3fdab06
--- /dev/null
@@ -0,0 +1,12 @@
+--TEST--
+Testing __callstatic declaration in interface with missing the 'static' modifier
+--FILE--
+<?php
+
+interface a {
+       function __callstatic($a, $b);
+}
+
+?>
+--EXPECTF--
+Fatal error: The magic method __callStatic() must have public visibility and be static in %s on line %d
diff --git a/Zend/tests/magic_methods_007.phpt b/Zend/tests/magic_methods_007.phpt
new file mode 100644 (file)
index 0000000..0f3b9e5
--- /dev/null
@@ -0,0 +1,12 @@
+--TEST--
+Testing __set() declaration in abstract class with wrong modifier
+--FILE--
+<?php
+
+abstract class b {
+       abstract protected function __set($a);
+}
+
+?>
+--EXPECTF--
+Fatal error: The magic method __set() must have public visibility and can not be static in %s on line %d
diff --git a/Zend/tests/magic_methods_008.phpt b/Zend/tests/magic_methods_008.phpt
new file mode 100644 (file)
index 0000000..b3f7362
--- /dev/null
@@ -0,0 +1,17 @@
+--TEST--
+Testing __set implementation with wrong declaration
+--FILE--
+<?php
+
+abstract class b {
+       abstract function __set($a, $b);
+}
+
+class a extends b {
+       private function __set($a, $b) {
+       }
+}
+
+?>
+--EXPECTF--
+Fatal error: The magic method __set() must have public visibility and can not be static in %s on line %d
diff --git a/Zend/tests/magic_methods_009.phpt b/Zend/tests/magic_methods_009.phpt
new file mode 100644 (file)
index 0000000..aac3d4c
--- /dev/null
@@ -0,0 +1,13 @@
+--TEST--
+Testing __callstatic declaration with wrong modifier
+--FILE--
+<?php
+
+class a {
+       static protected function __callstatic($a, $b) {
+       }
+}
+
+?>
+--EXPECTF--
+Fatal error: The magic method __callStatic() must have public visibility and be static in %s on line %d
diff --git a/Zend/tests/magic_methods_010.phpt b/Zend/tests/magic_methods_010.phpt
new file mode 100644 (file)
index 0000000..33e6b87
--- /dev/null
@@ -0,0 +1,13 @@
+--TEST--
+Testing __toString() declaration with wrong modifier
+--FILE--
+<?php
+
+class a {
+       static protected function __toString($a, $b) {
+       }
+}
+
+?>
+--EXPECTF--
+Fatal error: The magic method __toString() must have public visibility and can not be static in %s on line %d
index c5f46469b75d41107aeaa74d8c37c72e9204d605..c11de553f38003191da0167817f35795669be6ce 100644 (file)
@@ -1293,7 +1293,37 @@ void zend_do_begin_function_declaration(znode *function_token, znode *function_n
                        fn_flags |= ZEND_ACC_PUBLIC;
                }
 
-               if (!(CG(active_class_entry)->ce_flags & ZEND_ACC_INTERFACE)) {
+               if (CG(active_class_entry)->ce_flags & ZEND_ACC_INTERFACE) {
+                       if ((lcname_len == sizeof(ZEND_CALL_FUNC_NAME)-1) && (ZEND_U_EQUAL(Z_TYPE(function_name->u.constant), lcname, lcname_len, ZEND_CALL_FUNC_NAME, sizeof(ZEND_CALL_FUNC_NAME)-1))) {
+                               if (fn_flags & ((ZEND_ACC_PPP_MASK | ZEND_ACC_STATIC) ^ ZEND_ACC_PUBLIC)) {
+                                       zend_error(E_COMPILE_ERROR, "The magic method __call() must have public visibility and can not be static");
+                               }
+                       } else if ((lcname_len == sizeof(ZEND_CALLSTATIC_FUNC_NAME)-1) && (ZEND_U_EQUAL(Z_TYPE(function_name->u.constant), lcname, lcname_len, ZEND_CALLSTATIC_FUNC_NAME, sizeof(ZEND_CALLSTATIC_FUNC_NAME)-1))) {
+                               if ((fn_flags & (ZEND_ACC_PPP_MASK ^ ZEND_ACC_PUBLIC)) || (fn_flags & ZEND_ACC_STATIC) == 0) {
+                                       zend_error(E_COMPILE_ERROR, "The magic method __callStatic() must have public visibility and be static");
+                               }
+                       } else if ((lcname_len == sizeof(ZEND_GET_FUNC_NAME)-1) && (ZEND_U_EQUAL(Z_TYPE(function_name->u.constant), lcname, lcname_len, ZEND_GET_FUNC_NAME, sizeof(ZEND_GET_FUNC_NAME)-1))) {
+                               if (fn_flags & ((ZEND_ACC_PPP_MASK | ZEND_ACC_STATIC) ^ ZEND_ACC_PUBLIC)) {
+                                       zend_error(E_COMPILE_ERROR, "The magic method __get() must have public visibility and can not be static");
+                               }
+                       } else if ((lcname_len == sizeof(ZEND_SET_FUNC_NAME)-1) && (ZEND_U_EQUAL(Z_TYPE(function_name->u.constant), lcname, lcname_len, ZEND_SET_FUNC_NAME, sizeof(ZEND_SET_FUNC_NAME)-1))) {
+                               if (fn_flags & ((ZEND_ACC_PPP_MASK | ZEND_ACC_STATIC) ^ ZEND_ACC_PUBLIC)) {
+                                       zend_error(E_COMPILE_ERROR, "The magic method __set() must have public visibility and can not be static");
+                               }
+                       } else if ((lcname_len == sizeof(ZEND_UNSET_FUNC_NAME)-1) && (ZEND_U_EQUAL(Z_TYPE(function_name->u.constant), lcname, lcname_len, ZEND_UNSET_FUNC_NAME, sizeof(ZEND_UNSET_FUNC_NAME)-1))) {
+                               if (fn_flags & ((ZEND_ACC_PPP_MASK | ZEND_ACC_STATIC) ^ ZEND_ACC_PUBLIC)) {
+                                       zend_error(E_COMPILE_ERROR, "The magic method __unset() must have public visibility and can not be static");
+                               }
+                       } else if ((lcname_len == sizeof(ZEND_ISSET_FUNC_NAME)-1) && (ZEND_U_EQUAL(Z_TYPE(function_name->u.constant), lcname, lcname_len, ZEND_ISSET_FUNC_NAME, sizeof(ZEND_ISSET_FUNC_NAME)-1))) {
+                               if (fn_flags & ((ZEND_ACC_PPP_MASK | ZEND_ACC_STATIC) ^ ZEND_ACC_PUBLIC)) {
+                                       zend_error(E_COMPILE_ERROR, "The magic method __isset() must have public visibility and can not be static");
+                               }
+                       } else if ((lcname_len == sizeof(ZEND_TOSTRING_FUNC_NAME)-1) && (ZEND_U_EQUAL(Z_TYPE(function_name->u.constant), lcname, lcname_len, ZEND_TOSTRING_FUNC_NAME, sizeof(ZEND_TOSTRING_FUNC_NAME)-1))) {
+                               if (fn_flags & ((ZEND_ACC_PPP_MASK | ZEND_ACC_STATIC) ^ ZEND_ACC_PUBLIC)) {
+                                       zend_error(E_COMPILE_ERROR, "The magic method __toString() must have public visibility and can not be static");
+                               }
+                       }
+               } else {
                        zstr short_class_name;
                        unsigned int short_class_name_length;
                        zstr short_class_lcname;
@@ -1334,18 +1364,39 @@ void zend_do_begin_function_declaration(znode *function_token, znode *function_n
                        } else if ((lcname_len == sizeof(ZEND_CLONE_FUNC_NAME)-1) && (ZEND_U_EQUAL(Z_TYPE(function_name->u.constant), lcname, lcname_len, ZEND_CLONE_FUNC_NAME, sizeof(ZEND_CLONE_FUNC_NAME)-1))) {
                                CG(active_class_entry)->clone = (zend_function *) CG(active_op_array);
                        } else if ((lcname_len == sizeof(ZEND_CALL_FUNC_NAME)-1) && (ZEND_U_EQUAL(Z_TYPE(function_name->u.constant), lcname, lcname_len, ZEND_CALL_FUNC_NAME, sizeof(ZEND_CALL_FUNC_NAME)-1))) {
+                               if (fn_flags & ((ZEND_ACC_PPP_MASK | ZEND_ACC_STATIC) ^ ZEND_ACC_PUBLIC)) {
+                                       zend_error(E_COMPILE_ERROR, "The magic method __call() must have public visibility and can not be static");
+                               }
                                CG(active_class_entry)->__call = (zend_function *) CG(active_op_array);
                        } else if ((lcname_len == sizeof(ZEND_CALLSTATIC_FUNC_NAME)-1) && (ZEND_U_EQUAL(Z_TYPE(function_name->u.constant), lcname, lcname_len, ZEND_CALLSTATIC_FUNC_NAME, sizeof(ZEND_CALLSTATIC_FUNC_NAME)-1))) {
+                               if ((fn_flags & (ZEND_ACC_PPP_MASK ^ ZEND_ACC_PUBLIC)) || (fn_flags & ZEND_ACC_STATIC) == 0) {
+                                       zend_error(E_COMPILE_ERROR, "The magic method __callStatic() must have public visibility and be static");
+                               }
                                CG(active_class_entry)->__callstatic = (zend_function *) CG(active_op_array);
                        } else if ((lcname_len == sizeof(ZEND_GET_FUNC_NAME)-1) && (ZEND_U_EQUAL(Z_TYPE(function_name->u.constant), lcname, lcname_len, ZEND_GET_FUNC_NAME, sizeof(ZEND_GET_FUNC_NAME)-1))) {
+                               if (fn_flags & ((ZEND_ACC_PPP_MASK | ZEND_ACC_STATIC) ^ ZEND_ACC_PUBLIC)) {
+                                       zend_error(E_COMPILE_ERROR, "The magic method __get() must have public visibility and can not be static");
+                               }
                                CG(active_class_entry)->__get = (zend_function *) CG(active_op_array);
                        } else if ((lcname_len == sizeof(ZEND_SET_FUNC_NAME)-1) && (ZEND_U_EQUAL(Z_TYPE(function_name->u.constant), lcname, lcname_len, ZEND_SET_FUNC_NAME, sizeof(ZEND_SET_FUNC_NAME)-1))) {
+                               if (fn_flags & ((ZEND_ACC_PPP_MASK | ZEND_ACC_STATIC) ^ ZEND_ACC_PUBLIC)) {
+                                       zend_error(E_COMPILE_ERROR, "The magic method __set() must have public visibility and can not be static");
+                               }
                                CG(active_class_entry)->__set = (zend_function *) CG(active_op_array);
                        } else if ((lcname_len == sizeof(ZEND_UNSET_FUNC_NAME)-1) && (ZEND_U_EQUAL(Z_TYPE(function_name->u.constant), lcname, lcname_len, ZEND_UNSET_FUNC_NAME, sizeof(ZEND_UNSET_FUNC_NAME)-1))) {
+                               if (fn_flags & ((ZEND_ACC_PPP_MASK | ZEND_ACC_STATIC) ^ ZEND_ACC_PUBLIC)) {
+                                       zend_error(E_COMPILE_ERROR, "The magic method __unset() must have public visibility and can not be static");
+                               }
                                CG(active_class_entry)->__unset = (zend_function *) CG(active_op_array);
                        } else if ((lcname_len == sizeof(ZEND_ISSET_FUNC_NAME)-1) && (ZEND_U_EQUAL(Z_TYPE(function_name->u.constant), lcname, lcname_len, ZEND_ISSET_FUNC_NAME, sizeof(ZEND_ISSET_FUNC_NAME)-1))) {
+                               if (fn_flags & ((ZEND_ACC_PPP_MASK | ZEND_ACC_STATIC) ^ ZEND_ACC_PUBLIC)) {
+                                       zend_error(E_COMPILE_ERROR, "The magic method __isset() must have public visibility and can not be static");
+                               }
                                CG(active_class_entry)->__isset = (zend_function *) CG(active_op_array);
                        } else if ((lcname_len == sizeof(ZEND_TOSTRING_FUNC_NAME)-1) && (ZEND_U_EQUAL(Z_TYPE(function_name->u.constant), lcname, lcname_len, ZEND_TOSTRING_FUNC_NAME, sizeof(ZEND_TOSTRING_FUNC_NAME)-1))) {
+                               if (fn_flags & ((ZEND_ACC_PPP_MASK | ZEND_ACC_STATIC) ^ ZEND_ACC_PUBLIC)) {
+                                       zend_error(E_COMPILE_ERROR, "The magic method __toString() must have public visibility and can not be static");
+                               }
                                CG(active_class_entry)->__tostring = (zend_function *) CG(active_op_array);
                        } else if (!(fn_flags & ZEND_ACC_STATIC)) {
                                CG(active_op_array)->fn_flags |= ZEND_ACC_ALLOW_STATIC;
index b5b7705769ae56319f5bd7bcd96c2f5f4a3aadc2..5706a7c004b54b97b35d04aefaefc3adf26b41a6 100644 (file)
@@ -21,16 +21,5 @@ class B extends A {
 $b = new B();
 $b->test();
 ?>
---EXPECT--
-In A::__call(test1, array(1,a))
-object(B)#1 (0) {
-}
-In A::__call(test2, array(1,a))
-object(B)#1 (0) {
-}
-In A::__call(test3, array(1,a))
-object(B)#1 (0) {
-}
-In A::__call(test4, array(1,a))
-object(B)#1 (0) {
-}
+--EXPECTF--
+Fatal error: The magic method __call() must have public visibility and can not be static in %s on line %d