Skip to content

Commit c2086f9

Browse files
committed
Restrict -> in const expr to enums
1 parent a7d8a4b commit c2086f9

12 files changed

+153
-79
lines changed

Zend/tests/prop_const_expr/__get.phpt

Lines changed: 0 additions & 21 deletions
This file was deleted.

Zend/tests/prop_const_expr/basic.phpt

Lines changed: 13 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -1,37 +1,27 @@
11
--TEST--
2-
Allow properties in constant expressions
2+
Allow fetching properties in constant expressions on enums
33
--FILE--
44
<?php
55

6-
class A {
7-
public $prop = 'A::$prop';
6+
enum A: string {
7+
case Case = 'A::Case';
88
}
99

10-
enum B: string {
11-
case Case = 'B::Case';
12-
}
13-
14-
const A_prop = (new A)->prop;
15-
const B_name = B::Case->name;
16-
const B_value = B::Case->value;
10+
const A_name = A::Case->name;
11+
const A_value = A::Case->value;
1712

18-
var_dump(A_prop);
19-
var_dump(B_name);
20-
var_dump(B_value);
13+
var_dump(A_name);
14+
var_dump(A_value);
2115

22-
const A_prop_nullsafe = (new A)?->prop;
23-
const B_name_nullsafe = B::Case?->name;
24-
const B_value_nullsafe = B::Case?->value;
16+
const A_name_nullsafe = A::Case?->name;
17+
const A_value_nullsafe = A::Case?->value;
2518

26-
var_dump(A_prop_nullsafe);
27-
var_dump(B_name_nullsafe);
28-
var_dump(B_value_nullsafe);
19+
var_dump(A_name_nullsafe);
20+
var_dump(A_value_nullsafe);
2921

3022
?>
3123
--EXPECT--
32-
string(8) "A::$prop"
3324
string(4) "Case"
34-
string(7) "B::Case"
35-
string(8) "A::$prop"
25+
string(7) "A::Case"
3626
string(4) "Case"
37-
string(7) "B::Case"
27+
string(7) "A::Case"

Zend/tests/prop_const_expr/basic_nullsafe.phpt

Lines changed: 2 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -4,8 +4,6 @@ Nullsafe property constant expression
44
<?php
55

66
class Printer {
7-
public $test = 42;
8-
97
public function __construct() {
108
echo "Printer\n";
119
}
@@ -29,7 +27,7 @@ var_dump(E);
2927
const F = (null)?->{new Printer};
3028
var_dump(F);
3129

32-
const G = (null)?->test + (new Printer)->test;
30+
const G = (null)?->test + (new Printer ? 1 : 0);
3331
var_dump(G);
3432

3533
?>
@@ -45,4 +43,4 @@ Warning: Trying to access array offset on value of type null in %s on line %d
4543
NULL
4644
NULL
4745
Printer
48-
int(42)
46+
int(1)
Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
--TEST--
2+
Property fetch in default arg
3+
--FILE--
4+
<?php
5+
6+
enum A {
7+
case B;
8+
}
9+
10+
function test($bName = A::B->name) {
11+
echo $bName, "\n";
12+
}
13+
14+
test();
15+
test('C');
16+
17+
?>
18+
--EXPECT--
19+
B
20+
C
Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
--TEST--
2+
Disallow fetching properties in constant expressions on non-enums
3+
--FILE--
4+
<?php
5+
6+
class A {
7+
public $prop = 42;
8+
}
9+
10+
const A_prop = (new A)->prop;
11+
12+
?>
13+
--EXPECTF--
14+
Fatal error: Uncaught Error: Fetching properties on non-enums in constant expressions is not allowed in %s:%d
15+
Stack trace:
16+
#0 {main}
17+
thrown in %s on line %d
Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
--TEST--
2+
RHS gets evaluated before throwing error when accessing properties on non-enums in constant expressions
3+
--FILE--
4+
<?php
5+
6+
class A {
7+
public $prop = 42;
8+
}
9+
10+
class Printer {
11+
public function __construct() {
12+
echo "Printer\n";
13+
return 'printer';
14+
}
15+
}
16+
17+
const A_prop = (new A)->{new Printer ? 'printer' : null};
18+
19+
?>
20+
--EXPECTF--
21+
Printer
22+
23+
Fatal error: Uncaught Error: Fetching properties on non-enums in constant expressions is not allowed in %s:%d
24+
Stack trace:
25+
#0 {main}
26+
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+
Disallow nullsafe fetching properties in constant expressions on non-enums
3+
--FILE--
4+
<?php
5+
6+
class A {
7+
public $prop = 42;
8+
}
9+
10+
const A_prop = (new A)?->prop;
11+
12+
?>
13+
--EXPECTF--
14+
Fatal error: Uncaught Error: Fetching properties on non-enums in constant expressions is not allowed in %s:%d
15+
Stack trace:
16+
#0 {main}
17+
thrown in %s on line %d
Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
--TEST--
2+
Error when fetching properties on non-enums in constant expressions is catchable
3+
--FILE--
4+
<?php
5+
6+
class A {
7+
public $prop = 42;
8+
}
9+
10+
function foo($prop = (new A)->prop) {}
11+
12+
function test() {
13+
try {
14+
foo();
15+
} catch (Error $e) {
16+
echo $e->getMessage(), "\n";
17+
}
18+
}
19+
20+
test();
21+
test();
22+
23+
?>
24+
--EXPECT--
25+
Fetching properties on non-enums in constant expressions is not allowed
26+
Fetching properties on non-enums in constant expressions is not allowed
Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
--TEST--
2+
Property fetch in property initializer
3+
--FILE--
4+
<?php
5+
6+
enum A: int {
7+
case B = 42;
8+
}
9+
10+
class C {
11+
public int $d = A::B->value;
12+
}
13+
14+
$c = new C();
15+
var_dump($c->d);
16+
17+
?>
18+
--EXPECT--
19+
int(42)

Zend/tests/prop_const_expr/refcount.phpt

Lines changed: 0 additions & 27 deletions
This file was deleted.

Zend/tests/prop_const_expr/rhs_prop_not_found.phpt

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,14 +1,16 @@
11
--TEST--
2-
Property constant expression rhs error
2+
Property not found error
33
--FILE--
44
<?php
55

6-
class A {}
6+
enum A {
7+
case B;
8+
}
79

8-
const A_prop = (new A)->prop;
10+
const A_prop = A::B->prop;
911
var_dump(A_prop);
1012

11-
const A_prop_nullsafe = (new A)?->prop;
13+
const A_prop_nullsafe = A::B?->prop;
1214
var_dump(A_prop_nullsafe);
1315

1416
?>

Zend/zend_ast.c

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -958,6 +958,13 @@ ZEND_API zend_result ZEND_FASTCALL zend_ast_evaluate_ex(zval *result, zend_ast *
958958
}
959959

960960
zend_object *zobj = Z_OBJ(op1);
961+
if (!(zobj->ce->ce_flags & ZEND_ACC_ENUM)) {
962+
zend_throw_error(NULL, "Fetching properties on non-enums in constant expressions is not allowed");
963+
zval_ptr_dtor_nogc(&op1);
964+
zval_ptr_dtor_nogc(&op2);
965+
return FAILURE;
966+
}
967+
961968
zend_string *name = Z_STR(op2);
962969
zval *property_result = zend_read_property_ex(scope, zobj, name, 0, result);
963970
if (EG(exception)) {

0 commit comments

Comments
 (0)