diff --git a/Zend/Optimizer/zend_inference.c b/Zend/Optimizer/zend_inference.c index dff89b16f9d4..97dfeb977293 100644 --- a/Zend/Optimizer/zend_inference.c +++ b/Zend/Optimizer/zend_inference.c @@ -3849,7 +3849,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); diff --git a/Zend/tests/gh20403.phpt b/Zend/tests/gh20403.phpt new file mode 100644 index 000000000000..8ac0c782b92b --- /dev/null +++ b/Zend/tests/gh20403.phpt @@ -0,0 +1,17 @@ +--TEST-- +GH-20403 (Heap buffer overflow in zval_undefined_cv() when unsetting through an uninitialized typed static property) +--FILE-- +x); + +?> +===DONE=== +--EXPECTF-- +Warning: Undefined variable $x in %s on line %d +===DONE=== diff --git a/Zend/tests/oss_fuzz_429429090.phpt b/Zend/tests/oss_fuzz_429429090.phpt new file mode 100644 index 000000000000..d5279c2806ac --- /dev/null +++ b/Zend/tests/oss_fuzz_429429090.phpt @@ -0,0 +1,20 @@ +--TEST-- +OSS-Fuzz #429429090: FETCH_OBJ_UNSET IS_UNDEF result +--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 ae0b337ed2a6..d42f5220cfd1 100644 --- a/Zend/zend_execute.c +++ b/Zend/zend_execute.c @@ -3453,6 +3453,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); @@ -3603,6 +3606,11 @@ static zend_never_inline zend_result zend_fetch_static_property_address_ex(zval return FAILURE; } + if (UNEXPECTED(Z_TYPE_P(*retval) == IS_UNDEF) + && (fetch_type == BP_VAR_IS || fetch_type == BP_VAR_UNSET)) { + return FAILURE; + } + *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 df255c5a868f..d0cf893778a3 100644 --- a/Zend/zend_vm_def.h +++ b/Zend/zend_vm_def.h @@ -1839,7 +1839,7 @@ ZEND_VM_HELPER(zend_fetch_static_prop_helper, ANY, ANY, int type) SAVE_OPLINE(); if (UNEXPECTED(zend_fetch_static_property_address(&prop, NULL, opline->extended_value & ~ZEND_FETCH_OBJ_FLAGS, type, opline->extended_value OPLINE_CC EXECUTE_DATA_CC) != SUCCESS)) { - ZEND_ASSERT(EG(exception) || (type == BP_VAR_IS)); + ZEND_ASSERT(EG(exception) || (type == BP_VAR_IS) || (type == BP_VAR_UNSET)); prop = &EG(uninitialized_zval); } diff --git a/Zend/zend_vm_execute.h b/Zend/zend_vm_execute.h index 4b313f20cd39..a8efecc3f9d5 100644 --- a/Zend/zend_vm_execute.h +++ b/Zend/zend_vm_execute.h @@ -859,7 +859,7 @@ static zend_never_inline ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL zend_fetch_static SAVE_OPLINE(); if (UNEXPECTED(zend_fetch_static_property_address(&prop, NULL, opline->extended_value & ~ZEND_FETCH_OBJ_FLAGS, type, opline->extended_value OPLINE_CC EXECUTE_DATA_CC) != SUCCESS)) { - ZEND_ASSERT(EG(exception) || (type == BP_VAR_IS)); + ZEND_ASSERT(EG(exception) || (type == BP_VAR_IS) || (type == BP_VAR_UNSET)); prop = &EG(uninitialized_zval); }