From 62e843ffd13c0ddb9ae1aa9feb0a8fc506bdf9d6 Mon Sep 17 00:00:00 2001 From: Ilija Tovilo Date: Thu, 17 Jul 2025 19:07:15 +0200 Subject: [PATCH 1/2] Fix FETCH_OBJ_UNSET IS_UNDEF result UNSET_OBJ et al. do not expect to find IS_UNDEF results for IS_INDIRECT vars. To solve this, return IS_NULL from FETCH_OBJ_UNSET when properties are uninitialized. Do the same for FETCH_OBJ_IS, as we're otherwise copying IS_UNDEF into the VAR result, which is not a valid value for VAR. Fixes OSS-Fuzz #429429090 --- Zend/tests/oss_fuzz_429429090.phpt | 20 ++++++++++++++++++++ Zend/zend_execute.c | 8 ++++++++ Zend/zend_vm_def.h | 2 +- Zend/zend_vm_execute.h | 2 +- 4 files changed, 30 insertions(+), 2 deletions(-) create mode 100644 Zend/tests/oss_fuzz_429429090.phpt diff --git a/Zend/tests/oss_fuzz_429429090.phpt b/Zend/tests/oss_fuzz_429429090.phpt new file mode 100644 index 0000000000000..2b378a2deb483 --- /dev/null +++ b/Zend/tests/oss_fuzz_429429090.phpt @@ -0,0 +1,20 @@ +--TEST-- +OSS-Fuzz #429429090 +--FILE-- +x[0]->prop); +unset($c->x[0]->prop); +isset(C::$y[0]->prop); +unset(C::$y[0]->prop); + +?> +===DONE=== +--EXPECT-- +===DONE=== diff --git a/Zend/zend_execute.c b/Zend/zend_execute.c index 734494d252da0..055a6d0e577b9 100644 --- a/Zend/zend_execute.c +++ b/Zend/zend_execute.c @@ -3533,6 +3533,9 @@ static zend_always_inline void zend_fetch_property_address(zval *result, zval *c } else if (UNEXPECTED(Z_ISERROR_P(ptr))) { ZVAL_ERROR(result); goto end; + } else if (type == BP_VAR_UNSET && UNEXPECTED(Z_TYPE_P(ptr) == IS_UNDEF)) { + ZVAL_NULL(result); + goto end; } ZVAL_INDIRECT(result, ptr); @@ -3684,6 +3687,11 @@ static zend_never_inline zval* zend_fetch_static_property_address_ex(zend_proper return NULL; } + if (UNEXPECTED(Z_TYPE_P(result) == IS_UNDEF) + && (fetch_type == BP_VAR_IS || fetch_type == BP_VAR_UNSET)) { + return NULL; + } + *prop_info = property_info; if (EXPECTED(op1_type == IS_CONST) diff --git a/Zend/zend_vm_def.h b/Zend/zend_vm_def.h index c0e05aef470ae..acfff780f49fa 100644 --- a/Zend/zend_vm_def.h +++ b/Zend/zend_vm_def.h @@ -1866,7 +1866,7 @@ ZEND_VM_INLINE_HELPER(zend_fetch_static_prop_helper, ANY, ANY, int type) &prop_info, opline->extended_value & ~ZEND_FETCH_OBJ_FLAGS, type, type == BP_VAR_W ? opline->extended_value : 0 OPLINE_CC EXECUTE_DATA_CC); if (UNEXPECTED(!prop)) { - ZEND_ASSERT(EG(exception) || (type == BP_VAR_IS)); + ZEND_ASSERT(EG(exception) || (type == BP_VAR_IS) || (type == BP_VAR_UNSET)); prop = &EG(uninitialized_zval); } else if (UNEXPECTED(prop_info->flags & ZEND_ACC_PPP_SET_MASK) && (type == BP_VAR_W || type == BP_VAR_RW || type == BP_VAR_UNSET) diff --git a/Zend/zend_vm_execute.h b/Zend/zend_vm_execute.h index 387a05943dd19..8ec182f284b44 100644 --- a/Zend/zend_vm_execute.h +++ b/Zend/zend_vm_execute.h @@ -892,7 +892,7 @@ static zend_always_inline ZEND_OPCODE_HANDLER_RET zend_fetch_static_prop_helper_ &prop_info, opline->extended_value & ~ZEND_FETCH_OBJ_FLAGS, type, type == BP_VAR_W ? opline->extended_value : 0 OPLINE_CC EXECUTE_DATA_CC); if (UNEXPECTED(!prop)) { - ZEND_ASSERT(EG(exception) || (type == BP_VAR_IS)); + ZEND_ASSERT(EG(exception) || (type == BP_VAR_IS) || (type == BP_VAR_UNSET)); prop = &EG(uninitialized_zval); } else if (UNEXPECTED(prop_info->flags & ZEND_ACC_PPP_SET_MASK) && (type == BP_VAR_W || type == BP_VAR_RW || type == BP_VAR_UNSET) From e857b2faef7ff2ca42c52953177425629fe35679 Mon Sep 17 00:00:00 2001 From: Ilija Tovilo Date: Thu, 17 Jul 2025 22:41:09 +0200 Subject: [PATCH 2/2] Fix ZEND_FETCH_STATIC_PROP_IS type inference --- Zend/Optimizer/zend_inference.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Zend/Optimizer/zend_inference.c b/Zend/Optimizer/zend_inference.c index f146a741439d5..31bd2ab5e339a 100644 --- a/Zend/Optimizer/zend_inference.c +++ b/Zend/Optimizer/zend_inference.c @@ -3835,7 +3835,7 @@ static zend_always_inline zend_result _zend_update_type_info( tmp &= ~MAY_BE_RC1; } if (opline->opcode == ZEND_FETCH_STATIC_PROP_IS) { - tmp |= MAY_BE_UNDEF; + tmp |= MAY_BE_NULL; } } UPDATE_SSA_TYPE(tmp, ssa_op->result_def);