Skip to content

Commit 0c65b39

Browse files
authored
Allow FETCH_OBJ_W and FETCH_STATIC_PROP_W to return INDIRECT/UNDEF zval for uninitialized typed properties (php#11048)
1 parent 51faf04 commit 0c65b39

File tree

7 files changed

+63
-38
lines changed

7 files changed

+63
-38
lines changed

Zend/Optimizer/zend_inference.c

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3436,6 +3436,9 @@ static zend_always_inline int _zend_update_type_info(
34363436
tmp |= zend_fetch_prop_type(script, prop_info, &ce);
34373437
if (opline->result_type == IS_VAR) {
34383438
tmp |= MAY_BE_REF | MAY_BE_INDIRECT;
3439+
if ((opline->extended_value & ZEND_FETCH_OBJ_FLAGS) == ZEND_FETCH_DIM_WRITE) {
3440+
tmp |= MAY_BE_UNDEF;
3441+
}
34393442
} else if (!(opline->op1_type & (IS_VAR|IS_TMP_VAR)) || !(t1 & MAY_BE_RC1)) {
34403443
zend_class_entry *ce = NULL;
34413444

@@ -3473,6 +3476,9 @@ static zend_always_inline int _zend_update_type_info(
34733476
zend_fetch_static_prop_info(script, op_array, ssa, opline), &ce);
34743477
if (opline->result_type == IS_VAR) {
34753478
tmp |= MAY_BE_REF | MAY_BE_INDIRECT;
3479+
if ((opline->extended_value & ZEND_FETCH_OBJ_FLAGS) == ZEND_FETCH_DIM_WRITE) {
3480+
tmp |= MAY_BE_UNDEF;
3481+
}
34763482
} else {
34773483
if (!result_may_be_separated(ssa, ssa_op)) {
34783484
tmp &= ~MAY_BE_RC1;

Zend/zend_execute.c

Lines changed: 2 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -3087,7 +3087,7 @@ static zend_never_inline bool zend_handle_fetch_obj_flags(
30873087
return 1;
30883088
}
30893089

3090-
static zend_always_inline void zend_fetch_property_address(zval *result, zval *container, uint32_t container_op_type, zval *prop_ptr, uint32_t prop_op_type, void **cache_slot, int type, uint32_t flags, bool init_undef OPLINE_DC EXECUTE_DATA_DC)
3090+
static zend_always_inline void zend_fetch_property_address(zval *result, zval *container, uint32_t container_op_type, zval *prop_ptr, uint32_t prop_op_type, void **cache_slot, int type, uint32_t flags OPLINE_DC EXECUTE_DATA_DC)
30913091
{
30923092
zval *ptr;
30933093
zend_object *zobj;
@@ -3203,9 +3203,6 @@ static zend_always_inline void zend_fetch_property_address(zval *result, zval *c
32033203
}
32043204
}
32053205
}
3206-
if (init_undef && UNEXPECTED(Z_TYPE_P(ptr) == IS_UNDEF)) {
3207-
ZVAL_NULL(ptr);
3208-
}
32093206

32103207
end:
32113208
if (prop_op_type != IS_CONST) {
@@ -3219,7 +3216,7 @@ static zend_always_inline void zend_assign_to_property_reference(zval *container
32193216
void **cache_addr = (prop_op_type == IS_CONST) ? CACHE_ADDR(opline->extended_value & ~ZEND_RETURNS_FUNCTION) : NULL;
32203217

32213218
zend_fetch_property_address(variable_ptr, container, container_op_type, prop_ptr, prop_op_type,
3222-
cache_addr, BP_VAR_W, 0, 0 OPLINE_CC EXECUTE_DATA_CC);
3219+
cache_addr, BP_VAR_W, 0 OPLINE_CC EXECUTE_DATA_CC);
32233220

32243221
if (EXPECTED(Z_TYPE_P(variable_ptr) == IS_INDIRECT)) {
32253222
variable_ptr = Z_INDIRECT_P(variable_ptr);

Zend/zend_object_handlers.c

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1037,6 +1037,8 @@ ZEND_API zval *zend_std_get_property_ptr_ptr(zend_object *zobj, zend_string *nam
10371037
} else if (prop_info && UNEXPECTED(prop_info->flags & ZEND_ACC_READONLY)) {
10381038
/* Readonly property, delegate to read_property + write_property. */
10391039
retval = NULL;
1040+
} else if (!prop_info || !ZEND_TYPE_IS_SET(prop_info->type)) {
1041+
ZVAL_NULL(retval);
10401042
}
10411043
} else {
10421044
/* we do have getter - fail and let it try again with usual get/set */

Zend/zend_vm_def.h

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -2157,7 +2157,7 @@ ZEND_VM_HANDLER(85, ZEND_FETCH_OBJ_W, VAR|UNUSED|THIS|CV, CONST|TMPVAR|CV, FETCH
21572157
zend_fetch_property_address(
21582158
result, container, OP1_TYPE, property, OP2_TYPE,
21592159
((OP2_TYPE == IS_CONST) ? CACHE_ADDR(opline->extended_value & ~ZEND_FETCH_OBJ_FLAGS) : NULL),
2160-
BP_VAR_W, opline->extended_value & ZEND_FETCH_OBJ_FLAGS, 1 OPLINE_CC EXECUTE_DATA_CC);
2160+
BP_VAR_W, opline->extended_value & ZEND_FETCH_OBJ_FLAGS OPLINE_CC EXECUTE_DATA_CC);
21612161
FREE_OP2();
21622162
if (OP1_TYPE == IS_VAR) {
21632163
FREE_VAR_PTR_AND_EXTRACT_RESULT_IF_NECESSARY(opline->op1.var);
@@ -2174,7 +2174,7 @@ ZEND_VM_HANDLER(88, ZEND_FETCH_OBJ_RW, VAR|UNUSED|THIS|CV, CONST|TMPVAR|CV, CACH
21742174
container = GET_OP1_OBJ_ZVAL_PTR_PTR_UNDEF(BP_VAR_RW);
21752175
property = GET_OP2_ZVAL_PTR(BP_VAR_R);
21762176
result = EX_VAR(opline->result.var);
2177-
zend_fetch_property_address(result, container, OP1_TYPE, property, OP2_TYPE, ((OP2_TYPE == IS_CONST) ? CACHE_ADDR(opline->extended_value) : NULL), BP_VAR_RW, 0, 1 OPLINE_CC EXECUTE_DATA_CC);
2177+
zend_fetch_property_address(result, container, OP1_TYPE, property, OP2_TYPE, ((OP2_TYPE == IS_CONST) ? CACHE_ADDR(opline->extended_value) : NULL), BP_VAR_RW, 0 OPLINE_CC EXECUTE_DATA_CC);
21782178
FREE_OP2();
21792179
if (OP1_TYPE == IS_VAR) {
21802180
FREE_VAR_PTR_AND_EXTRACT_RESULT_IF_NECESSARY(opline->op1.var);
@@ -2321,7 +2321,7 @@ ZEND_VM_HANDLER(97, ZEND_FETCH_OBJ_UNSET, VAR|UNUSED|THIS|CV, CONST|TMPVAR|CV, C
23212321
container = GET_OP1_OBJ_ZVAL_PTR_PTR_UNDEF(BP_VAR_UNSET);
23222322
property = GET_OP2_ZVAL_PTR(BP_VAR_R);
23232323
result = EX_VAR(opline->result.var);
2324-
zend_fetch_property_address(result, container, OP1_TYPE, property, OP2_TYPE, ((OP2_TYPE == IS_CONST) ? CACHE_ADDR(opline->extended_value) : NULL), BP_VAR_UNSET, 0, 1 OPLINE_CC EXECUTE_DATA_CC);
2324+
zend_fetch_property_address(result, container, OP1_TYPE, property, OP2_TYPE, ((OP2_TYPE == IS_CONST) ? CACHE_ADDR(opline->extended_value) : NULL), BP_VAR_UNSET, 0 OPLINE_CC EXECUTE_DATA_CC);
23252325
FREE_OP2();
23262326
if (OP1_TYPE == IS_VAR) {
23272327
FREE_VAR_PTR_AND_EXTRACT_RESULT_IF_NECESSARY(opline->op1.var);

0 commit comments

Comments
 (0)