]> granicus.if.org Git - php/commitdiff
Fixed bug #53826
authorNikita Popov <nikita.ppv@gmail.com>
Thu, 18 Feb 2021 13:16:48 +0000 (14:16 +0100)
committerNikita Popov <nikita.ppv@gmail.com>
Thu, 18 Feb 2021 13:17:47 +0000 (14:17 +0100)
We should handle the case where the method doesn't exist, and
where it is not visible the same way.

NEWS
Zend/tests/bug53826.phpt [new file with mode: 0644]
Zend/zend_object_handlers.c

diff --git a/NEWS b/NEWS
index c6b626bb53a1c6f95dec0e1f3a8d11fb41ecaeb6..ba6465fbcc9659b2259fc638ea93676e765bc93b 100644 (file)
--- a/NEWS
+++ b/NEWS
@@ -7,6 +7,8 @@ PHP                                                                        NEWS
   . Added missing hashtable insertion APIs for arr/obj/ref. (Sara)
   . Fixed bug #75474 (function scope static variables are not bound to a unique
     function). (Nikita)
+  . Fixed bug #53826 (__callStatic fired in base class through a parent call if
+    the method is private). (Nikita)
 
 - FTP:
   . Convert resource<ftp> to object \FTPConnection. (Sara)
diff --git a/Zend/tests/bug53826.phpt b/Zend/tests/bug53826.phpt
new file mode 100644 (file)
index 0000000..3f0a069
--- /dev/null
@@ -0,0 +1,33 @@
+--TEST--
+Bug #53826: __callStatic fired in base class through a parent call if the method is private
+--FILE--
+<?php
+
+class A1 {
+       public function __call($method, $args) { echo "__call\n"; }
+       public static function __callStatic($method, $args) { echo "__callStatic\n"; }
+}
+
+class A2 { // A1 with private function test
+       public function __call($method, $args) { echo "__call\n"; }
+       public static function __callStatic($method, $args) { echo "__callStatic\n"; }
+       private function test() {}
+}
+
+class B1 extends A1 {
+       public function test(){ parent::test(); }
+}
+
+class B2 extends A2 {
+       public function test(){ parent::test(); }
+}
+
+$test1 = new B1;
+$test2 = new B2;
+$test1->test();
+$test2->test();
+
+?>
+--EXPECT--
+__call
+__call
index e99af731f94e320162e5632cf05935360e2f25a6..b903afb8ba5c64dc254826466546229d50976eea 100644 (file)
@@ -1263,11 +1263,29 @@ static zend_always_inline zend_function *zend_get_user_callstatic_function(zend_
 }
 /* }}} */
 
+static zend_always_inline zend_function *get_static_method_fallback(
+               zend_class_entry *ce, zend_string *function_name)
+{
+       zend_object *object;
+       if (ce->__call &&
+               (object = zend_get_this_object(EG(current_execute_data))) != NULL &&
+               instanceof_function(object->ce, ce)) {
+               /* Call the top-level defined __call().
+                * see: tests/classes/__call_004.phpt  */
+
+               ZEND_ASSERT(object->ce->__call);
+               return zend_get_user_call_function(object->ce, function_name);
+       } else if (ce->__callstatic) {
+               return zend_get_user_callstatic_function(ce, function_name);
+       } else {
+               return NULL;
+       }
+}
+
 ZEND_API zend_function *zend_std_get_static_method(zend_class_entry *ce, zend_string *function_name, const zval *key) /* {{{ */
 {
        zend_function *fbc = NULL;
        zend_string *lc_function_name;
-       zend_object *object;
        zend_class_entry *scope;
 
        if (EXPECTED(key != NULL)) {
@@ -1293,19 +1311,7 @@ ZEND_API zend_function *zend_std_get_static_method(zend_class_entry *ce, zend_st
                        if (UNEXPECTED(!key)) {
                                zend_string_release_ex(lc_function_name, 0);
                        }
-                       if (ce->__call &&
-                               (object = zend_get_this_object(EG(current_execute_data))) != NULL &&
-                           instanceof_function(object->ce, ce)) {
-                               /* Call the top-level defined __call().
-                                * see: tests/classes/__call_004.phpt  */
-
-                               ZEND_ASSERT(object->ce->__call);
-                               return zend_get_user_call_function(object->ce, function_name);
-                       } else if (ce->__callstatic) {
-                               return zend_get_user_callstatic_function(ce, function_name);
-                       } else {
-                               return NULL;
-                       }
+                       return get_static_method_fallback(ce, function_name);
                }
        } while (0);
 
@@ -1321,12 +1327,11 @@ ZEND_API zend_function *zend_std_get_static_method(zend_class_entry *ce, zend_st
                if (UNEXPECTED(fbc->common.scope != scope)) {
                        if (UNEXPECTED(fbc->op_array.fn_flags & ZEND_ACC_PRIVATE)
                         || UNEXPECTED(!zend_check_protected(zend_get_function_root_class(fbc), scope))) {
-                               if (ce->__callstatic) {
-                                       fbc = zend_get_user_callstatic_function(ce, function_name);
-                               } else {
+                               zend_function *fallback_fbc = get_static_method_fallback(ce, function_name);
+                               if (!fallback_fbc) {
                                        zend_bad_method_call(fbc, function_name, scope);
-                                       fbc = NULL;
                                }
+                               fbc = fallback_fbc;
                        }
                }
        }