Skip to content

Commit db2e2af

Browse files
committed
Fixed bug #53826
We should handle the case where the method doesn't exist, and where it is not visible the same way.
1 parent 6e988ea commit db2e2af

File tree

3 files changed

+58
-18
lines changed

3 files changed

+58
-18
lines changed

NEWS

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,8 @@ PHP NEWS
77
. Added missing hashtable insertion APIs for arr/obj/ref. (Sara)
88
. Fixed bug #75474 (function scope static variables are not bound to a unique
99
function). (Nikita)
10+
. Fixed bug #53826 (__callStatic fired in base class through a parent call if
11+
the method is private). (Nikita)
1012

1113
- FTP:
1214
. Convert resource<ftp> to object \FTPConnection. (Sara)

Zend/tests/bug53826.phpt

Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,33 @@
1+
--TEST--
2+
Bug #53826: __callStatic fired in base class through a parent call if the method is private
3+
--FILE--
4+
<?php
5+
6+
class A1 {
7+
public function __call($method, $args) { echo "__call\n"; }
8+
public static function __callStatic($method, $args) { echo "__callStatic\n"; }
9+
}
10+
11+
class A2 { // A1 with private function test
12+
public function __call($method, $args) { echo "__call\n"; }
13+
public static function __callStatic($method, $args) { echo "__callStatic\n"; }
14+
private function test() {}
15+
}
16+
17+
class B1 extends A1 {
18+
public function test(){ parent::test(); }
19+
}
20+
21+
class B2 extends A2 {
22+
public function test(){ parent::test(); }
23+
}
24+
25+
$test1 = new B1;
26+
$test2 = new B2;
27+
$test1->test();
28+
$test2->test();
29+
30+
?>
31+
--EXPECT--
32+
__call
33+
__call

Zend/zend_object_handlers.c

Lines changed: 23 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -1263,11 +1263,29 @@ static zend_always_inline zend_function *zend_get_user_callstatic_function(zend_
12631263
}
12641264
/* }}} */
12651265

1266+
static zend_always_inline zend_function *get_static_method_fallback(
1267+
zend_class_entry *ce, zend_string *function_name)
1268+
{
1269+
zend_object *object;
1270+
if (ce->__call &&
1271+
(object = zend_get_this_object(EG(current_execute_data))) != NULL &&
1272+
instanceof_function(object->ce, ce)) {
1273+
/* Call the top-level defined __call().
1274+
* see: tests/classes/__call_004.phpt */
1275+
1276+
ZEND_ASSERT(object->ce->__call);
1277+
return zend_get_user_call_function(object->ce, function_name);
1278+
} else if (ce->__callstatic) {
1279+
return zend_get_user_callstatic_function(ce, function_name);
1280+
} else {
1281+
return NULL;
1282+
}
1283+
}
1284+
12661285
ZEND_API zend_function *zend_std_get_static_method(zend_class_entry *ce, zend_string *function_name, const zval *key) /* {{{ */
12671286
{
12681287
zend_function *fbc = NULL;
12691288
zend_string *lc_function_name;
1270-
zend_object *object;
12711289
zend_class_entry *scope;
12721290

12731291
if (EXPECTED(key != NULL)) {
@@ -1293,19 +1311,7 @@ ZEND_API zend_function *zend_std_get_static_method(zend_class_entry *ce, zend_st
12931311
if (UNEXPECTED(!key)) {
12941312
zend_string_release_ex(lc_function_name, 0);
12951313
}
1296-
if (ce->__call &&
1297-
(object = zend_get_this_object(EG(current_execute_data))) != NULL &&
1298-
instanceof_function(object->ce, ce)) {
1299-
/* Call the top-level defined __call().
1300-
* see: tests/classes/__call_004.phpt */
1301-
1302-
ZEND_ASSERT(object->ce->__call);
1303-
return zend_get_user_call_function(object->ce, function_name);
1304-
} else if (ce->__callstatic) {
1305-
return zend_get_user_callstatic_function(ce, function_name);
1306-
} else {
1307-
return NULL;
1308-
}
1314+
return get_static_method_fallback(ce, function_name);
13091315
}
13101316
} while (0);
13111317

@@ -1321,12 +1327,11 @@ ZEND_API zend_function *zend_std_get_static_method(zend_class_entry *ce, zend_st
13211327
if (UNEXPECTED(fbc->common.scope != scope)) {
13221328
if (UNEXPECTED(fbc->op_array.fn_flags & ZEND_ACC_PRIVATE)
13231329
|| UNEXPECTED(!zend_check_protected(zend_get_function_root_class(fbc), scope))) {
1324-
if (ce->__callstatic) {
1325-
fbc = zend_get_user_callstatic_function(ce, function_name);
1326-
} else {
1330+
zend_function *fallback_fbc = get_static_method_fallback(ce, function_name);
1331+
if (!fallback_fbc) {
13271332
zend_bad_method_call(fbc, function_name, scope);
1328-
fbc = NULL;
13291333
}
1334+
fbc = fallback_fbc;
13301335
}
13311336
}
13321337
}

0 commit comments

Comments
 (0)