From d9cbc3117c4186766f67723c6ed765c80d55fa96 Mon Sep 17 00:00:00 2001 From: Niels Dossche <7771979+ndossche@users.noreply.github.com> Date: Wed, 21 Jan 2026 01:12:55 +0100 Subject: [PATCH] Fix hooked object properties overflow The computed number of properties using zend_hash_num_elements(zobj->properties) is incorrect when the object contains virtual properties. We don't have a trivial way to find the number of properties virtual properties that need to be added to this number, so just append with zend_hash_add_new() instead. Fixes GH-20479 Closes GH-20988 --- NEWS | 1 + Zend/tests/property_hooks/gh20479.phpt | 40 ++++++++++++++++++++++++++ Zend/zend_property_hooks.c | 2 +- 3 files changed, 42 insertions(+), 1 deletion(-) create mode 100644 Zend/tests/property_hooks/gh20479.phpt diff --git a/NEWS b/NEWS index 7d90a01f51d..9b8840c39cd 100644 --- a/NEWS +++ b/NEWS @@ -15,6 +15,7 @@ PHP NEWS . Fix OSS-Fuzz #438780145 (Nested finally with repeated return type check may uaf). (ilutov) . Fixed bug GH-20905 (Lazy proxy bailing __clone assertion). (ilutov) + . Fixed bug GH-20479 (Hooked object properties overflow). (ndossche) - Date: . Update timelib to 2022.16. (Derick) diff --git a/Zend/tests/property_hooks/gh20479.phpt b/Zend/tests/property_hooks/gh20479.phpt new file mode 100644 index 00000000000..c53c4e4240c --- /dev/null +++ b/Zend/tests/property_hooks/gh20479.phpt @@ -0,0 +1,40 @@ +--TEST-- +GH-20479: Hooked object properties overflow +--CREDITS-- +Viet Hoang Luu (@vi3tL0u1s) +--FILE-- +g = $obj->h = 'x'; +var_export($obj); + +?> +--EXPECT-- +\Trigger::__set_state(array( + 'a' => 'x', + 'b' => 'x', + 'c' => 'x', + 'd' => 'x', + 'e' => 'x', + 'f' => 'x', + 'trigger' => 'trigger', + 'h' => 'x', + 'g' => 'x', +)) diff --git a/Zend/zend_property_hooks.c b/Zend/zend_property_hooks.c index 01a8afb1693..57e22f23ad7 100644 --- a/Zend/zend_property_hooks.c +++ b/Zend/zend_property_hooks.c @@ -121,7 +121,7 @@ skip_property: if (Z_TYPE_P(prop_value) == IS_INDIRECT) { continue; } - zval *tmp = _zend_hash_append(properties, prop_name, prop_value); + zval *tmp = zend_hash_add_new(properties, prop_name, prop_value); Z_TRY_ADDREF_P(tmp); } ZEND_HASH_FOREACH_END(); }