From 8a392eddf94df292c3f3a8d99baf14beb666ea37 Mon Sep 17 00:00:00 2001 From: George Peter Banyard Date: Sun, 3 Sep 2023 00:12:25 +0100 Subject: [PATCH] Fix OSS Fuzz #61865: Undef variable in ++/-- for declared property that is unset in error handler Reorder when we assign the property value to NULL which is identical to a3a3964497922bcd74282685218d90acea69c296 Just for the declared property case instead of dynamic. Closes GH-12114 --- NEWS | 2 ++ ...declared_property_unset_error_handler.phpt | 18 +++++++++++++ ...declared_property_unset_error_handler.phpt | 20 +++++++++++++++ ...declared_property_unset_error_handler.phpt | 20 +++++++++++++++ ...declared_property_unset_error_handler.phpt | 18 +++++++++++++ ...declared_property_unset_error_handler.phpt | 18 +++++++++++++ ...rty_converted_to_obj_in_error_handler.phpt | 25 +++++++++++++++++++ Zend/zend_object_handlers.c | 5 +++- 8 files changed, 125 insertions(+), 1 deletion(-) create mode 100644 Zend/tests/in-de-crement/oss-fuzz-61865_binop_declared_property_unset_error_handler.phpt create mode 100644 Zend/tests/in-de-crement/oss-fuzz-61865_postdec_declared_property_unset_error_handler.phpt create mode 100644 Zend/tests/in-de-crement/oss-fuzz-61865_postinc_declared_property_unset_error_handler.phpt create mode 100644 Zend/tests/in-de-crement/oss-fuzz-61865_predec_declared_property_unset_error_handler.phpt create mode 100644 Zend/tests/in-de-crement/oss-fuzz-61865_preinc_declared_property_unset_error_handler.phpt create mode 100644 Zend/tests/in-de-crement/unset_property_converted_to_obj_in_error_handler.phpt diff --git a/NEWS b/NEWS index 954ed0944bb..85391264f05 100644 --- a/NEWS +++ b/NEWS @@ -10,6 +10,8 @@ PHP NEWS closures). (ilutov) . Fixed bug GH-12060 (Internal iterator rewind handler is called twice). (ju1ius) + . Fixed OSS Fuzz #61865 (Undef variable in ++/-- for declared property + that is unset in error handler). (Girgias) - FPM: 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 00000000000..c5a9fe3c803 --- /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 00000000000..6fb1d18f694 --- /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 00000000000..94bccd7a82f --- /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 00000000000..f077ecb53dc --- /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 00000000000..a63e08e49c9 --- /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 00000000000..d435c9fb402 --- /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 5146b086491..573d9eb106d 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. */