]> granicus.if.org Git - php/commitdiff
Fixed __call() to be invoked on private/protected method access through callback
authorDmitry Stogov <dmitry@php.net>
Wed, 14 Jan 2009 11:56:24 +0000 (11:56 +0000)
committerDmitry Stogov <dmitry@php.net>
Wed, 14 Jan 2009 11:56:24 +0000 (11:56 +0000)
s

Zend/tests/access_modifiers_012.phpt [new file with mode: 0644]
Zend/zend_API.c

diff --git a/Zend/tests/access_modifiers_012.phpt b/Zend/tests/access_modifiers_012.phpt
new file mode 100644 (file)
index 0000000..ac4d72c
--- /dev/null
@@ -0,0 +1,21 @@
+--TEST--
+Trigger __call() in lieu of non visible methods when called via a callback.
+--FILE--
+<?php
+class C {
+       protected function prot() { }
+       private function priv() { }
+       public function __call($name, $args)    {
+        echo "In __call() for method $name()\n";
+    }
+}
+
+$c = new C;
+call_user_func(array($c, 'none'));
+call_user_func(array($c, 'prot'));
+call_user_func(array($c, 'priv'));
+?>
+--EXPECTF--
+In __call() for method none()
+In __call() for method prot()
+In __call() for method priv()
index febd091564504b4f5a76729e1b8d30ae16ee57a2..b8555f0ff6c84761cfa29d7989a11c94ad94d4ec 100644 (file)
@@ -2892,31 +2892,56 @@ static int zend_is_callable_check_func(int check_flags, zval *callable, zend_fca
                                fcc->function_handler = priv_fbc;
                        }
                }
-       } else if (fcc->object_ptr) {
-               if (Z_OBJ_HT_P(fcc->object_ptr)->get_method) {
-                       zstr method = mname;
-                       int method_len = mlen;
-
-                       if (UG(unicode) && Z_TYPE_P(callable) == IS_STRING) {
-                               zend_string_to_unicode(ZEND_U_CONVERTER(UG(runtime_encoding_conv)), &method.u, &method_len, mname.s, mlen TSRMLS_CC);
-                       } else if (!UG(unicode) && Z_TYPE_P(callable) == IS_UNICODE) {
-                               zend_unicode_to_string(ZEND_U_CONVERTER(UG(runtime_encoding_conv)), &method.s, &method_len, mname.u, mlen TSRMLS_CC);
-                       }       
-                       fcc->function_handler = Z_OBJ_HT_P(fcc->object_ptr)->get_method(&fcc->object_ptr, method, method_len TSRMLS_CC);
-                       if (method.v != mname.v) {
-                               efree(method.v);
+               if ((check_flags & IS_CALLABLE_CHECK_NO_ACCESS) == 0 &&
+                   (fcc->calling_scope &&
+                    (fcc->calling_scope->__call ||
+                     fcc->calling_scope->__callstatic))) {
+                       if (fcc->function_handler->op_array.fn_flags & ZEND_ACC_PRIVATE) {
+                               if (!zend_check_private(fcc->function_handler, fcc->object_ptr ? Z_OBJCE_P(fcc->object_ptr) : EG(scope), lmname, lmlen TSRMLS_CC)) {
+                                       retval = 0;
+                                       fcc->function_handler = NULL;
+                                       goto get_function_via_handler;
+                               }
+                       } else if ((fcc->function_handler->common.fn_flags & ZEND_ACC_PROTECTED)) {
+                               if (!zend_check_protected(fcc->function_handler->common.scope, EG(scope))) {
+                                       retval = 0;
+                                       fcc->function_handler = NULL;
+                                       goto get_function_via_handler;
+                               }
                        }
-                       retval = fcc->function_handler ? 1 : 0;
-                       call_via_handler = 1;
                }
-       } else if (fcc->calling_scope) {
-               if (fcc->calling_scope->get_static_method) {
-                       fcc->function_handler = fcc->calling_scope->get_static_method(fcc->calling_scope, Z_TYPE_P(callable), mname, mlen TSRMLS_CC);
-               } else {
-                       fcc->function_handler = zend_std_get_static_method(fcc->calling_scope, Z_TYPE_P(callable), mname, mlen TSRMLS_CC);
+       } else {
+get_function_via_handler:
+               if (fcc->object_ptr) {
+                       if (Z_OBJ_HT_P(fcc->object_ptr)->get_method) {
+                               zstr method = mname;
+                               int method_len = mlen;
+
+                               if (UG(unicode) && Z_TYPE_P(callable) == IS_STRING) {
+                                       zend_string_to_unicode(ZEND_U_CONVERTER(UG(runtime_encoding_conv)), &method.u, &method_len, mname.s, mlen TSRMLS_CC);
+                               } else if (!UG(unicode) && Z_TYPE_P(callable) == IS_UNICODE) {
+                                       zend_unicode_to_string(ZEND_U_CONVERTER(UG(runtime_encoding_conv)), &method.s, &method_len, mname.u, mlen TSRMLS_CC);
+                               }       
+                               fcc->function_handler = Z_OBJ_HT_P(fcc->object_ptr)->get_method(&fcc->object_ptr, method, method_len TSRMLS_CC);
+                               if (method.v != mname.v) {
+                                       efree(method.v);
+                               }
+                               if (fcc->function_handler) {
+                                       retval = 1;
+                                       call_via_handler = (fcc->function_handler->common.fn_flags & ZEND_ACC_CALL_VIA_HANDLER) != 0;
+                               }
+                       }
+               } else if (fcc->calling_scope) {
+                       if (fcc->calling_scope->get_static_method) {
+                               fcc->function_handler = fcc->calling_scope->get_static_method(fcc->calling_scope, Z_TYPE_P(callable), mname, mlen TSRMLS_CC);
+                       } else {
+                               fcc->function_handler = zend_std_get_static_method(fcc->calling_scope, Z_TYPE_P(callable), mname, mlen TSRMLS_CC);
+                       }
+                       if (fcc->function_handler) {
+                               retval = 1;
+                               call_via_handler = (fcc->function_handler->common.fn_flags & ZEND_ACC_CALL_VIA_HANDLER) != 0;
+                       }
                }
-               retval = fcc->function_handler ? 1 : 0;
-               call_via_handler = 1;
        }
 
        if (retval) {