]> granicus.if.org Git - php/commitdiff
Fixed bug #46246 (difference between call_user_func(array($this, $method)) and $this...
authorDmitry Stogov <dmitry@php.net>
Fri, 10 Oct 2008 15:19:22 +0000 (15:19 +0000)
committerDmitry Stogov <dmitry@php.net>
Fri, 10 Oct 2008 15:19:22 +0000 (15:19 +0000)
Zend/tests/bug46246.phpt [new file with mode: 0644]
Zend/zend_API.c

diff --git a/Zend/tests/bug46246.phpt b/Zend/tests/bug46246.phpt
new file mode 100644 (file)
index 0000000..a57222b
--- /dev/null
@@ -0,0 +1,40 @@
+--TEST--
+Bug #46246 (difference between call_user_func(array($this, $method)) and $this->$method())
+--FILE--
+<?php
+class A
+{
+       private function Test()
+       {
+               echo 'Hello from '.get_class($this)."\n";
+       }
+       
+       public function call($method, $args = array())
+       {
+               $this->Test();
+               $this->$method();
+               call_user_func(array($this, $method));
+       }
+}
+
+class B extends A
+{
+       protected function Test()
+       {
+               echo 'Overridden hello from '.get_class($this)."\n";
+       }
+}
+
+$a = new A;
+$b = new B;
+
+$a->call('Test');
+$b->call('Test');
+?>
+--EXPECT--
+Hello from A
+Hello from A
+Hello from A
+Hello from B
+Hello from B
+Hello from B
index 988a305407527e69733b32939b462d6a4a5180ab..fe1f640545feedfffef2340fdb1d6d1631f12f24 100644 (file)
@@ -2879,21 +2879,34 @@ static int zend_is_callable_check_func(int check_flags, zval *callable, zend_fca
        lmname = zend_u_str_case_fold(Z_TYPE_P(callable), mname, mlen, 1, &lmlen);
        if (zend_u_hash_find(ftable, Z_TYPE_P(callable), lmname, lmlen+1, (void**)&fcc->function_handler) == SUCCESS) {
                retval = 1;
-       } else if (fcc->object_pp && Z_OBJ_HT_PP(fcc->object_pp)->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_PP(fcc->object_pp)->get_method(fcc->object_pp, method, method_len TSRMLS_CC);
-               if (method.v != mname.v) {
-                       efree(method.v);
+               if ((fcc->function_handler->op_array.fn_flags & ZEND_ACC_CHANGED) &&
+                   EG(scope) &&
+                   instanceof_function(fcc->function_handler->common.scope, EG(scope) TSRMLS_CC)) {
+                       zend_function *priv_fbc;
+
+                       if (zend_u_hash_find(&EG(scope)->function_table, Z_TYPE_P(callable), lmname, lmlen+1, (void **) &priv_fbc)==SUCCESS
+                               && priv_fbc->common.fn_flags & ZEND_ACC_PRIVATE
+                               && priv_fbc->common.scope == EG(scope)) {
+                               fcc->function_handler = priv_fbc;
+                       }
+               }
+       } else if (fcc->object_pp) {
+               if (Z_OBJ_HT_PP(fcc->object_pp)->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_PP(fcc->object_pp)->get_method(fcc->object_pp, method, method_len TSRMLS_CC);
+                       if (method.v != mname.v) {
+                               efree(method.v);
+                       }
+                       retval = fcc->function_handler ? 1 : 0;
+                       call_via_handler = 1;
                }
-               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);