diff --git a/Zend/tests/in-de-crement/oss-fuzz-61865_binop_declared_property_unset_error_handler.phpt b/Zend/tests/in-de-crement/oss-fuzz-61865_binop_declared_property_unset_error_handler.phpt new file mode 100644 index 0000000000000..c5a9fe3c8032a --- /dev/null +++ b/Zend/tests/in-de-crement/oss-fuzz-61865_binop_declared_property_unset_error_handler.phpt @@ -0,0 +1,18 @@ +--TEST-- +OSS Fuzz #61865: Undef variable in ++/-- for declared property that is unset in error handler +--FILE-- +a); + } +} +$c = new C; +set_error_handler([$c,'errorHandler']); +unset($c->a); +$c->a += 5; +var_dump($c->a); +?> +--EXPECT-- +int(5) diff --git a/Zend/tests/in-de-crement/oss-fuzz-61865_postdec_declared_property_unset_error_handler.phpt b/Zend/tests/in-de-crement/oss-fuzz-61865_postdec_declared_property_unset_error_handler.phpt new file mode 100644 index 0000000000000..6fb1d18f69492 --- /dev/null +++ b/Zend/tests/in-de-crement/oss-fuzz-61865_postdec_declared_property_unset_error_handler.phpt @@ -0,0 +1,20 @@ +--TEST-- +OSS Fuzz #61865: Undef variable in ++/-- for declared property that is unset in error handler +--FILE-- +a); + } +} +$c = new C; +set_error_handler([$c,'errorHandler']); +unset($c->a); +$v = ($c->a--); +var_dump($c->a); +var_dump($v); +?> +--EXPECT-- +NULL +NULL diff --git a/Zend/tests/in-de-crement/oss-fuzz-61865_postinc_declared_property_unset_error_handler.phpt b/Zend/tests/in-de-crement/oss-fuzz-61865_postinc_declared_property_unset_error_handler.phpt new file mode 100644 index 0000000000000..94bccd7a82f80 --- /dev/null +++ b/Zend/tests/in-de-crement/oss-fuzz-61865_postinc_declared_property_unset_error_handler.phpt @@ -0,0 +1,20 @@ +--TEST-- +OSS Fuzz #61865: Undef variable in ++/-- for declared property that is unset in error handler +--FILE-- +a); + } +} +$c = new C; +set_error_handler([$c,'errorHandler']); +unset($c->a); +$v = ($c->a++); +var_dump($c->a); +var_dump($v); +?> +--EXPECT-- +int(1) +NULL diff --git a/Zend/tests/in-de-crement/oss-fuzz-61865_predec_declared_property_unset_error_handler.phpt b/Zend/tests/in-de-crement/oss-fuzz-61865_predec_declared_property_unset_error_handler.phpt new file mode 100644 index 0000000000000..f077ecb53dcad --- /dev/null +++ b/Zend/tests/in-de-crement/oss-fuzz-61865_predec_declared_property_unset_error_handler.phpt @@ -0,0 +1,18 @@ +--TEST-- +OSS Fuzz #61865: Undef variable in ++/-- for declared property that is unset in error handler +--FILE-- +a); + } +} +$c = new C; +set_error_handler([$c,'errorHandler']); +unset($c->a); +(--$c->a); +var_dump($c->a); +?> +--EXPECT-- +NULL diff --git a/Zend/tests/in-de-crement/oss-fuzz-61865_preinc_declared_property_unset_error_handler.phpt b/Zend/tests/in-de-crement/oss-fuzz-61865_preinc_declared_property_unset_error_handler.phpt new file mode 100644 index 0000000000000..a63e08e49c9dc --- /dev/null +++ b/Zend/tests/in-de-crement/oss-fuzz-61865_preinc_declared_property_unset_error_handler.phpt @@ -0,0 +1,18 @@ +--TEST-- +OSS Fuzz #61865: Undef variable in ++/-- for declared property that is unset in error handler +--FILE-- +a); + } +} +$c = new C; +set_error_handler([$c,'errorHandler']); +unset($c->a); +(++$c->a); +var_dump($c->a); +?> +--EXPECT-- +int(1) diff --git a/Zend/tests/in-de-crement/unset_property_converted_to_obj_in_error_handler.phpt b/Zend/tests/in-de-crement/unset_property_converted_to_obj_in_error_handler.phpt new file mode 100644 index 0000000000000..d435c9fb4029e --- /dev/null +++ b/Zend/tests/in-de-crement/unset_property_converted_to_obj_in_error_handler.phpt @@ -0,0 +1,25 @@ +--TEST-- +Unset declared property converted to object in error handler +--FILE-- +a = new stdClass(); + } +} +$c = new C; +set_error_handler([$c,'errorHandler']); +unset($c->a); + +try { + (++$c->a); +} catch (\TypeError $e) { + echo $e->getMessage(), PHP_EOL; +} +var_dump($c->a); +?> +--EXPECT-- +Cannot increment stdClass +object(stdClass)#2 (0) { +} diff --git a/Zend/zend_object_handlers.c b/Zend/zend_object_handlers.c index 5146b0864916d..573d9eb106df1 100644 --- a/Zend/zend_object_handlers.c +++ b/Zend/zend_object_handlers.c @@ -1117,8 +1117,11 @@ ZEND_API zval *zend_std_get_property_ptr_ptr(zend_object *zobj, zend_string *nam ZSTR_VAL(name)); retval = &EG(error_zval); } else { - ZVAL_NULL(retval); zend_error(E_WARNING, "Undefined property: %s::$%s", ZSTR_VAL(zobj->ce->name), ZSTR_VAL(name)); + /* An error handler may set the property */ + if (EXPECTED(Z_TYPE_P(retval) == IS_UNDEF)) { + ZVAL_NULL(retval); + } } } else if (prop_info && UNEXPECTED(prop_info->flags & ZEND_ACC_READONLY)) { /* Readonly property, delegate to read_property + write_property. */