From 3d3b22ddf249184ad9a442f4610428120d54d7ed Mon Sep 17 00:00:00 2001 From: Arnaud Le Blanc Date: Tue, 29 Oct 2024 13:02:56 +0100 Subject: [PATCH] Fix assertion failure in zend_std_read_property We asserted that Z_PROP_FLAG_P(retval) was exactly IS_PROP_UNINIT, but this is a bit field and it may contain irrelevant bits. For instance it may contain IS_PROP_REINITABLE during clone, or IS_PROP_LAZY if the object is lazy. Fixes GH-16615 Closes GH-16639 --- NEWS | 1 + Zend/tests/gh16615_001.phpt | 23 +++++++++++++++++++++++ Zend/tests/gh16615_002.phpt | 24 ++++++++++++++++++++++++ Zend/zend_object_handlers.c | 2 +- 4 files changed, 49 insertions(+), 1 deletion(-) create mode 100644 Zend/tests/gh16615_001.phpt create mode 100644 Zend/tests/gh16615_002.phpt diff --git a/NEWS b/NEWS index 71e619788d0..683700f3a1c 100644 --- a/NEWS +++ b/NEWS @@ -7,6 +7,7 @@ PHP NEWS (nielsdos) . Fixed bug GH-16577 (EG(strtod_state).freelist leaks with opcache.preload). (nielsdos) + . Fixed bug GH-16615 (Assertion failure in zend_std_read_property). (Arnaud) - DOM: . Fixed bug GH-16594 (Assertion failure in DOM -> before). (nielsdos) diff --git a/Zend/tests/gh16615_001.phpt b/Zend/tests/gh16615_001.phpt new file mode 100644 index 00000000000..a6bb2c743d4 --- /dev/null +++ b/Zend/tests/gh16615_001.phpt @@ -0,0 +1,23 @@ +--TEST-- +GH-16615 001 (Assertion failure in zend_std_read_property) +--FILE-- + $value; + } +} + +$reflector = new ReflectionClass(Foo::class); + +// Adds IS_PROP_LAZY to prop flags +$foo = $reflector->newLazyGhost(function ($ghost) { + $ghost->bar = 'bar'; +}); + +echo $foo->bar; + +?> +--EXPECT-- +bar diff --git a/Zend/tests/gh16615_002.phpt b/Zend/tests/gh16615_002.phpt new file mode 100644 index 00000000000..eff3398f277 --- /dev/null +++ b/Zend/tests/gh16615_002.phpt @@ -0,0 +1,24 @@ +--TEST-- +GH-16615 002 (Assertion failure in zend_std_read_property) +--FILE-- + $value; + } + public function __clone() { + try { + echo $this->bar; + } catch (Error $e) { + printf("%s: %s\n", $e::class, $e->getMessage()); + } + } +} + +// Adds IS_PROP_REINITABLE to prop flags +clone new Foo(); + +?> +--EXPECT-- +Error: Typed property Foo::$bar must not be accessed before initialization diff --git a/Zend/zend_object_handlers.c b/Zend/zend_object_handlers.c index 17b85dbfe2e..f0868509274 100644 --- a/Zend/zend_object_handlers.c +++ b/Zend/zend_object_handlers.c @@ -791,7 +791,7 @@ try_again: if (UNEXPECTED(Z_TYPE_P(retval) == IS_UNDEF)) { /* As hooked properties can't be unset, the only way to end up with an undef * value is via an uninitialized property. */ - ZEND_ASSERT(Z_PROP_FLAG_P(retval) == IS_PROP_UNINIT); + ZEND_ASSERT(Z_PROP_FLAG_P(retval) & IS_PROP_UNINIT); goto uninit_error; }