Skip to content

Commit 770616b

Browse files
authored
Fix param with hooks but no visibility not treated as cpp (phpGH-15442)
Fixes phpGH-15438
1 parent 144c086 commit 770616b

File tree

4 files changed

+54
-9
lines changed

4 files changed

+54
-9
lines changed

NEWS

+2
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,8 @@ PHP NEWS
55
- Core:
66
. Fixed bug GH-15408 (MSan false-positve on zend_max_execution_timer).
77
(zeriyoshi)
8+
. Fixed bug GH-15438 (Hooks on constructor promoted properties without
9+
visibility are ignored). (ilutov)
810

911
15 Aug 2024, PHP 8.4.0beta3
1012

+20
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
--TEST--
2+
GH-15438: Promoted properties with hooks but no visibility
3+
--FILE--
4+
<?php
5+
6+
class C {
7+
public function __construct(
8+
$prop { set => $value * 2; }
9+
) {}
10+
}
11+
12+
$c = new C(42);
13+
var_dump($c);
14+
15+
?>
16+
--EXPECTF--
17+
object(C)#%d (1) {
18+
["prop"]=>
19+
int(84)
20+
}
+20
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
--TEST--
2+
GH-15438: Untyped promoted, hooked properties with no default value default to null
3+
--FILE--
4+
<?php
5+
6+
class C {
7+
public function __construct(
8+
public $prop { set => $value * 2; }
9+
) {}
10+
}
11+
12+
$c = new ReflectionClass(C::class)->newInstanceWithoutConstructor();
13+
var_dump($c);
14+
15+
?>
16+
--EXPECTF--
17+
object(C)#%d (1) {
18+
["prop"]=>
19+
NULL
20+
}

Zend/zend_compile.c

+12-9
Original file line numberDiff line numberDiff line change
@@ -7570,6 +7570,7 @@ static void zend_compile_params(zend_ast *ast, zend_ast *return_type_ast, uint32
75707570
bool is_ref = (param_ast->attr & ZEND_PARAM_REF) != 0;
75717571
bool is_variadic = (param_ast->attr & ZEND_PARAM_VARIADIC) != 0;
75727572
uint32_t property_flags = param_ast->attr & (ZEND_ACC_PPP_MASK | ZEND_ACC_READONLY);
7573+
bool is_promoted = property_flags || hooks_ast;
75737574

75747575
znode var_node, default_node;
75757576
uint8_t opcode;
@@ -7626,14 +7627,14 @@ static void zend_compile_params(zend_ast *ast, zend_ast *return_type_ast, uint32
76267627
if (attributes_ast) {
76277628
zend_compile_attributes(
76287629
&op_array->attributes, attributes_ast, i + 1, ZEND_ATTRIBUTE_TARGET_PARAMETER,
7629-
property_flags ? ZEND_ATTRIBUTE_TARGET_PROPERTY : 0
7630+
is_promoted ? ZEND_ATTRIBUTE_TARGET_PROPERTY : 0
76307631
);
76317632
}
76327633

76337634
bool forced_allow_nullable = false;
76347635
if (type_ast) {
76357636
uint32_t default_type = *default_ast_ptr ? Z_TYPE(default_node.u.constant) : IS_UNDEF;
7636-
bool force_nullable = default_type == IS_NULL && !property_flags;
7637+
bool force_nullable = default_type == IS_NULL && !is_promoted;
76377638

76387639
op_array->fn_flags |= ZEND_ACC_HAS_TYPE_HINTS;
76397640
arg_info->type = zend_compile_typename_ex(type_ast, force_nullable, &forced_allow_nullable);
@@ -7696,14 +7697,14 @@ static void zend_compile_params(zend_ast *ast, zend_ast *return_type_ast, uint32
76967697
}
76977698

76987699
uint32_t arg_info_flags = _ZEND_ARG_INFO_FLAGS(is_ref, is_variadic, /* is_tentative */ 0)
7699-
| (property_flags ? _ZEND_IS_PROMOTED_BIT : 0);
7700+
| (is_promoted ? _ZEND_IS_PROMOTED_BIT : 0);
77007701
ZEND_TYPE_FULL_MASK(arg_info->type) |= arg_info_flags;
77017702
if (opcode == ZEND_RECV) {
77027703
opline->op2.num = type_ast ?
77037704
ZEND_TYPE_FULL_MASK(arg_info->type) : MAY_BE_ANY;
77047705
}
77057706

7706-
if (property_flags) {
7707+
if (is_promoted) {
77077708
zend_op_array *op_array = CG(active_op_array);
77087709
zend_class_entry *scope = op_array->scope;
77097710

@@ -7790,9 +7791,11 @@ static void zend_compile_params(zend_ast *ast, zend_ast *return_type_ast, uint32
77907791

77917792
for (i = 0; i < list->children; i++) {
77927793
zend_ast *param_ast = list->child[i];
7794+
zend_ast *hooks_ast = param_ast->child[5];
77937795
bool is_ref = (param_ast->attr & ZEND_PARAM_REF) != 0;
77947796
uint32_t flags = param_ast->attr & (ZEND_ACC_PPP_MASK | ZEND_ACC_READONLY);
7795-
if (!flags) {
7797+
bool is_promoted = flags || hooks_ast;
7798+
if (!is_promoted) {
77967799
continue;
77977800
}
77987801

@@ -8543,6 +8546,10 @@ static void zend_compile_property_hooks(
85438546
/* Will be removed again, in case of Iterator or IteratorAggregate. */
85448547
ce->get_iterator = zend_hooked_object_get_iterator;
85458548
}
8549+
8550+
if (!prop_info->ce->parent_name) {
8551+
zend_verify_hooked_property(ce, prop_info, prop_name);
8552+
}
85468553
}
85478554

85488555
static void zend_compile_prop_decl(zend_ast *ast, zend_ast *type_ast, uint32_t flags, zend_ast *attr_ast) /* {{{ */
@@ -8679,10 +8686,6 @@ static void zend_compile_prop_decl(zend_ast *ast, zend_ast *type_ast, uint32_t f
86798686

86808687
if (hooks_ast) {
86818688
zend_compile_property_hooks(info, name, type_ast, zend_ast_get_list(hooks_ast));
8682-
8683-
if (!ce->parent_name) {
8684-
zend_verify_hooked_property(ce, info, name);
8685-
}
86868689
}
86878690

86888691
if (attr_ast) {

0 commit comments

Comments
 (0)