Skip to content

Commit 52495eb

Browse files
committed
handle more visibility
1 parent 2c5013a commit 52495eb

File tree

3 files changed

+82
-6
lines changed

3 files changed

+82
-6
lines changed

Zend/zend_object_handlers.c

Lines changed: 14 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -381,6 +381,7 @@ static zend_always_inline uintptr_t zend_get_property_offset(zend_class_entry *c
381381
if (flags & (ZEND_ACC_CHANGED|ZEND_ACC_PRIVATE|ZEND_ACC_PROTECTED)) {
382382
zend_class_entry *scope = get_fake_or_executed_scope();
383383

384+
check_lexical_scope:
384385
if (property_info->ce != scope) {
385386
if (flags & ZEND_ACC_CHANGED) {
386387
zend_property_info *p = zend_get_parent_private_property(scope, ce, member);
@@ -401,11 +402,11 @@ static zend_always_inline uintptr_t zend_get_property_offset(zend_class_entry *c
401402
if (property_info->ce != ce) {
402403
goto dynamic;
403404
} else {
404-
if (scope && scope->lexical_scope && scope->lexical_scope == ce) {
405-
// Allow access to private properties from within the same outer class
406-
goto found;
407-
}
408405
wrong:
406+
if (scope && scope->lexical_scope) {
407+
scope = scope->lexical_scope;
408+
goto check_lexical_scope;
409+
}
409410
/* Information was available, but we were denied access. Error out. */
410411
if (!silent) {
411412
zend_bad_property_access(property_info, ce, member);
@@ -1819,6 +1820,7 @@ ZEND_API zend_function *zend_std_get_method(zend_object **obj_ptr, zend_string *
18191820
/* Check access level */
18201821
if (fbc->op_array.fn_flags & (ZEND_ACC_CHANGED|ZEND_ACC_PRIVATE|ZEND_ACC_PROTECTED)) {
18211822
scope = zend_get_executed_scope();
1823+
zend_class_entry *original_scope = scope;
18221824
check_lexical_scope:
18231825

18241826
if (fbc->common.scope != scope) {
@@ -1841,7 +1843,7 @@ ZEND_API zend_function *zend_std_get_method(zend_object **obj_ptr, zend_string *
18411843
scope = scope->lexical_scope;
18421844
goto check_lexical_scope;
18431845
}
1844-
zend_bad_method_call(fbc, method_name, scope);
1846+
zend_bad_method_call(fbc, method_name, original_scope);
18451847
fbc = NULL;
18461848
}
18471849
}
@@ -1900,6 +1902,7 @@ ZEND_API zend_function *zend_std_get_static_method(zend_class_entry *ce, zend_st
19001902
fbc = Z_FUNC_P(func);
19011903
if (!(fbc->op_array.fn_flags & ZEND_ACC_PUBLIC)) {
19021904
zend_class_entry *scope = zend_get_executed_scope();
1905+
zend_class_entry *original_scope = scope;
19031906
check_lexical_scope:
19041907
if (UNEXPECTED(fbc->common.scope != scope)) {
19051908
if (UNEXPECTED(fbc->op_array.fn_flags & ZEND_ACC_PRIVATE)
@@ -1911,7 +1914,7 @@ ZEND_API zend_function *zend_std_get_static_method(zend_class_entry *ce, zend_st
19111914
goto check_lexical_scope;
19121915
}
19131916

1914-
zend_bad_method_call(fbc, function_name, scope);
1917+
zend_bad_method_call(fbc, function_name, original_scope);
19151918
}
19161919
fbc = fallback_fbc;
19171920
}
@@ -1988,10 +1991,15 @@ ZEND_API zval *zend_std_get_static_property_with_info(zend_class_entry *ce, zend
19881991

19891992
if (!(property_info->flags & ZEND_ACC_PUBLIC)) {
19901993
zend_class_entry *scope = get_fake_or_executed_scope();
1994+
check_lexical_scope:
19911995
if (property_info->ce != scope) {
19921996
if (UNEXPECTED(property_info->flags & ZEND_ACC_PRIVATE)
19931997
|| UNEXPECTED(!is_protected_compatible_scope(property_info->ce, scope))) {
19941998
if (type != BP_VAR_IS) {
1999+
if (scope && scope->lexical_scope) {
2000+
scope = scope->lexical_scope;
2001+
goto check_lexical_scope;
2002+
}
19952003
zend_bad_property_access(property_info, ce, property_name);
19962004
}
19972005
return NULL;
Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,30 @@
1+
--TEST--
2+
accessing sibling methods
3+
--FILE--
4+
<?php
5+
6+
class Outer {
7+
protected function test() {
8+
echo __METHOD__ . "\n";
9+
}
10+
protected class Middle {
11+
public static function test() {
12+
echo __METHOD__ . "\n";
13+
}
14+
}
15+
}
16+
17+
class Other extends Outer {
18+
class Inner {
19+
public function test() {
20+
Outer:>Middle::test();
21+
$t = new Outer();
22+
$t->test();
23+
}
24+
}
25+
}
26+
new Other:>Inner()->test();
27+
?>
28+
--EXPECT--
29+
Outer:>Middle::test
30+
Outer::test
Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,38 @@
1+
--TEST--
2+
deeply nested property visibility
3+
--FILE--
4+
<?php
5+
6+
class Outer {
7+
private int $i;
8+
private static int $j;
9+
class Middle {
10+
private int $i;
11+
private static int $j;
12+
class Inner {
13+
public static function test() {
14+
var_dump(Outer::$j = 5);
15+
var_dump(Outer:>Middle::$j = 42);
16+
$foo = new Outer();
17+
$foo->i = 42;
18+
var_dump($foo);
19+
$foo = new Outer:>Middle();
20+
$foo->i = 42;
21+
var_dump($foo);
22+
}
23+
}
24+
}
25+
}
26+
Outer:>Middle:>Inner::test();
27+
?>
28+
--EXPECT--
29+
int(5)
30+
int(42)
31+
object(Outer)#1 (1) {
32+
["i":"Outer":private]=>
33+
int(42)
34+
}
35+
object(Outer:>Middle)#2 (1) {
36+
["i":"Outer:>Middle":private]=>
37+
int(42)
38+
}

0 commit comments

Comments
 (0)