From 18556e7a33b57d66fff45de6bdcc2f43d18d1a24 Mon Sep 17 00:00:00 2001 From: Ilija Tovilo Date: Tue, 16 Jul 2024 11:55:55 +0200 Subject: [PATCH] Fix user-after-free in property coercion with __toString() This was only partially fixed in PHP-8.3. Backports and fixes the case for both initialized and uninitialized property writes. Fixes GH-14969 Closes GH-14971 --- Zend/tests/gh14969.phpt | 47 +++++++++++++++++++++++++++++++++++++ Zend/zend_object_handlers.c | 4 ++-- 2 files changed, 49 insertions(+), 2 deletions(-) create mode 100644 Zend/tests/gh14969.phpt diff --git a/Zend/tests/gh14969.phpt b/Zend/tests/gh14969.phpt new file mode 100644 index 0000000000000..dedbaa7456e00 --- /dev/null +++ b/Zend/tests/gh14969.phpt @@ -0,0 +1,47 @@ +--TEST-- +GH-14969: Crash on coercion with throwing __toString() +--FILE-- +prop = $c; +} catch (Throwable $e) { + echo $e->getMessage(), "\n"; +} +var_dump($d); + +$c = new C(); +$d->prop = 'foo'; +try { + $d->prop = $c; +} catch (Throwable $e) { + echo $e->getMessage(), "\n"; +} +var_dump($d); + +?> +--EXPECTF-- +C::__toString +object(D)#%d (0) { + ["prop"]=> + uninitialized(string) +} +C::__toString +object(D)#2 (1) { + ["prop"]=> + string(3) "foo" +} diff --git a/Zend/zend_object_handlers.c b/Zend/zend_object_handlers.c index 58301da038ce0..d4586e53e4b4a 100644 --- a/Zend/zend_object_handlers.c +++ b/Zend/zend_object_handlers.c @@ -819,7 +819,7 @@ ZEND_API zval *zend_std_write_property(zend_object *zobj, zend_string *name, zva ZVAL_COPY_VALUE(&tmp, value); if (UNEXPECTED(!zend_verify_property_type(prop_info, &tmp, property_uses_strict_types()))) { - Z_TRY_DELREF_P(value); + zval_ptr_dtor(&tmp); variable_ptr = &EG(error_zval); goto exit; } @@ -890,7 +890,7 @@ ZEND_API zval *zend_std_write_property(zend_object *zobj, zend_string *name, zva ZVAL_COPY_VALUE(&tmp, value); if (UNEXPECTED(!zend_verify_property_type(prop_info, &tmp, property_uses_strict_types()))) { - zval_ptr_dtor(value); + zval_ptr_dtor(&tmp); goto exit; } value = &tmp;