Skip to content

Commit 3130d4c

Browse files
committed
Fix segfault in format_default_value due to unexpected enum/object
Evaluating constants at comptime can result in arrays that contain objects. This is problematic for printing the default value of constant ASTs containing objects, because we don't actually know what the constructor arguments were. Avoid this by not propagating array constants. Fixes GH-11937
1 parent 0d922aa commit 3130d4c

File tree

6 files changed

+76
-9
lines changed

6 files changed

+76
-9
lines changed

Zend/zend_compile.c

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1468,7 +1468,7 @@ static bool can_ct_eval_const(zend_constant *c) {
14681468
&& (CG(compiler_options) & ZEND_COMPILE_WITH_FILE_CACHE))) {
14691469
return 1;
14701470
}
1471-
if (Z_TYPE(c->value) < IS_OBJECT
1471+
if (Z_TYPE(c->value) < IS_ARRAY
14721472
&& !(CG(compiler_options) & ZEND_COMPILE_NO_CONSTANT_SUBSTITUTION)) {
14731473
return 1;
14741474
}
@@ -1690,7 +1690,7 @@ static bool zend_try_ct_eval_class_const(zval *zv, zend_string *class_name, zend
16901690
c = &cc->value;
16911691

16921692
/* Substitute case-sensitive (or lowercase) persistent class constants */
1693-
if (Z_TYPE_P(c) < IS_OBJECT) {
1693+
if (Z_TYPE_P(c) < IS_ARRAY) {
16941694
ZVAL_COPY_OR_DUP(zv, c);
16951695
return 1;
16961696
}

ext/reflection/php_reflection.c

Lines changed: 0 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -638,13 +638,6 @@ static int format_default_value(smart_str *str, zval *value) {
638638
format_default_value(str, zv);
639639
} ZEND_HASH_FOREACH_END();
640640
smart_str_appendc(str, ']');
641-
} else if (Z_TYPE_P(value) == IS_OBJECT) {
642-
zend_object *obj = Z_OBJ_P(value);
643-
zend_class_entry *class = obj->ce;
644-
ZEND_ASSERT(class->ce_flags & ZEND_ACC_ENUM);
645-
smart_str_append(str, class->name);
646-
smart_str_appends(str, "::");
647-
smart_str_append(str, Z_STR_P(zend_enum_fetch_case_name(obj)));
648641
} else {
649642
ZEND_ASSERT(Z_TYPE_P(value) == IS_CONSTANT_AST);
650643
zend_string *ast_str = zend_ast_export("", Z_ASTVAL_P(value), "");

ext/reflection/tests/gh11937_1.inc

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
<?php
2+
3+
#[Attribute]
4+
class Attr {
5+
public function __construct(public $value) {}
6+
}
7+
8+
class Foo {
9+
public function __construct(public $value) {}
10+
}
11+
12+
#[Attr(new Foo(TestEnum::CASES))]
13+
function test() {}

ext/reflection/tests/gh11937_1.phpt

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,30 @@
1+
--TEST--
2+
GH-11937: Segfault in format_default_value due to unexpected enum/object
3+
--FILE--
4+
<?php
5+
6+
enum TestEnum {
7+
case One;
8+
case Two;
9+
const CASES = [self::One, self::Two];
10+
}
11+
12+
var_dump(TestEnum::CASES);
13+
14+
require __DIR__ . '/gh11937_1.inc';
15+
16+
echo (new ReflectionFunction('test'))->getAttributes('Attr')[0];
17+
18+
?>
19+
--EXPECT--
20+
array(2) {
21+
[0]=>
22+
enum(TestEnum::One)
23+
[1]=>
24+
enum(TestEnum::Two)
25+
}
26+
Attribute [ Attr ] {
27+
- Arguments [1] {
28+
Argument #0 [ new \Foo(TestEnum::CASES) ]
29+
}
30+
}

ext/reflection/tests/gh11937_2.inc

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
<?php
2+
3+
#[Attr(FOOS)]
4+
function test() {}

ext/reflection/tests/gh11937_2.phpt

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
--TEST--
2+
GH-11937: Segfault in format_default_value due to unexpected enum/object
3+
--FILE--
4+
<?php
5+
6+
class Foo {}
7+
8+
const FOOS = [new Foo()];
9+
10+
var_dump(FOOS);
11+
12+
require __DIR__ . '/gh11937_2.inc';
13+
14+
echo (new ReflectionFunction('test'))->getAttributes('Attr')[0];
15+
16+
?>
17+
--EXPECT--
18+
array(1) {
19+
[0]=>
20+
object(Foo)#1 (0) {
21+
}
22+
}
23+
Attribute [ Attr ] {
24+
- Arguments [1] {
25+
Argument #0 [ FOOS ]
26+
}
27+
}

0 commit comments

Comments
 (0)