Skip to content

Commit 6d83d35

Browse files
committed
Make Closure in const-expr scoping behavior consistent with other Closures
1 parent b895d42 commit 6d83d35

File tree

6 files changed

+134
-1
lines changed

6 files changed

+134
-1
lines changed
Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
--TEST--
2+
Closure in attribute may access private variables
3+
--EXTENSIONS--
4+
reflection
5+
--FILE--
6+
<?php
7+
8+
#[Attribute(Attribute::TARGET_CLASS | Attribute::IS_REPEATABLE)]
9+
class Attr {
10+
public function __construct(public Closure $value) {}
11+
}
12+
13+
#[Attr(static function (C $c) {
14+
echo $c->secret, PHP_EOL;
15+
})]
16+
class C {
17+
public function __construct(
18+
private string $secret,
19+
) {}
20+
}
21+
22+
foreach ((new ReflectionClass(C::class))->getAttributes() as $reflectionAttribute) {
23+
($reflectionAttribute->newInstance()->value)(new C('secret'));
24+
}
25+
26+
?>
27+
--EXPECT--
28+
secret
Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,35 @@
1+
--TEST--
2+
Closure in attribute may not access unrelated private variables
3+
--EXTENSIONS--
4+
reflection
5+
--FILE--
6+
<?php
7+
8+
#[Attribute(Attribute::TARGET_CLASS | Attribute::IS_REPEATABLE)]
9+
class Attr {
10+
public function __construct(public Closure $value) {}
11+
}
12+
13+
#[Attr(static function (E $e) {
14+
echo $e->secret, PHP_EOL;
15+
})]
16+
class C {
17+
}
18+
19+
class E {
20+
public function __construct(
21+
private string $secret,
22+
) {}
23+
}
24+
25+
foreach ((new ReflectionClass(C::class))->getAttributes() as $reflectionAttribute) {
26+
($reflectionAttribute->newInstance()->value)(new E('secret'));
27+
}
28+
29+
?>
30+
--EXPECTF--
31+
Fatal error: Uncaught Error: Cannot access private property E::$secret in %s:%d
32+
Stack trace:
33+
#0 %s(%d): C::{closure:%s:%d}(Object(E))
34+
#1 {main}
35+
thrown in %s on line %d
Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
--TEST--
2+
Disallows using variables.
3+
--FILE--
4+
<?php
5+
6+
$foo = "bar";
7+
8+
const Closure = function () {
9+
echo $foo, PHP_EOL;
10+
};
11+
12+
var_dump(Closure);
13+
(Closure)();
14+
15+
?>
16+
--EXPECTF--
17+
Fatal error: Closures in constant expressions must be "static" in %s on line %d
Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
--TEST--
2+
Closure in property initializer may access private variables
3+
--FILE--
4+
<?php
5+
6+
class C {
7+
public Closure $d = static function (C $c) {
8+
echo $c->secret, PHP_EOL;
9+
};
10+
11+
public function __construct(
12+
private string $secret,
13+
) {}
14+
}
15+
16+
$c = new C('secret');
17+
($c->d)($c);
18+
19+
20+
?>
21+
--EXPECTF--
22+
secret
Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,30 @@
1+
--TEST--
2+
Closure in property initializer may not access unrelated private variables
3+
--FILE--
4+
<?php
5+
6+
class C {
7+
public Closure $d = static function (E $e) {
8+
echo $e->secret, PHP_EOL;
9+
};
10+
11+
12+
}
13+
14+
class E {
15+
public function __construct(
16+
private string $secret,
17+
) {}
18+
}
19+
20+
$c = new C();
21+
($c->d)(new E('secret'));
22+
23+
24+
?>
25+
--EXPECTF--
26+
Fatal error: Uncaught Error: Cannot access private property E::$secret in %s:%d
27+
Stack trace:
28+
#0 %s(%d): C::{closure:%s:%d}(Object(E))
29+
#1 {main}
30+
thrown in %s on line %d

Zend/zend_ast.c

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -995,8 +995,9 @@ ZEND_API zend_result ZEND_FASTCALL zend_ast_evaluate_inner(
995995
{
996996
zend_ast *child = ast->child[0];
997997
zval *z = zend_ast_get_zval(child);
998+
zend_function *func = Z_PTR_P(z);
998999

999-
zend_create_closure(result, Z_PTR_P(z), NULL, NULL, NULL);
1000+
zend_create_closure(result, func, scope, scope, NULL);
10001001
return SUCCESS;
10011002
}
10021003
case ZEND_AST_PROP:

0 commit comments

Comments
 (0)