From 593d7800f9fdd130022bc2daece1940cb1b11251 Mon Sep 17 00:00:00 2001 From: Ilija Tovilo Date: Thu, 14 Nov 2024 22:32:05 +0100 Subject: [PATCH] Fix get_object_vars() for non-hooked props in hooked prop iter Very confusingly, the zend_hash_update_ind() variant unwraps indirects, rather than creating them. Don't use _zend_hash_append_ind() because the property might already exist. Fixes GH-16725 --- Zend/tests/gh16725.phpt | 27 +++++++++++++++++++++++++++ Zend/zend_property_hooks.c | 3 ++- 2 files changed, 29 insertions(+), 1 deletion(-) create mode 100644 Zend/tests/gh16725.phpt diff --git a/Zend/tests/gh16725.phpt b/Zend/tests/gh16725.phpt new file mode 100644 index 0000000000000..e9a2564fc0151 --- /dev/null +++ b/Zend/tests/gh16725.phpt @@ -0,0 +1,27 @@ +--TEST-- +GH-16725: Incorrect access check for non-hooked props in hooked object iterator +--FILE-- + 'bar'; } + + public function __construct( + private string $prop2, + ) {} + + public function jsonSerialize(): mixed { + return get_object_vars($this); + } +} + +$obj = new C('foo'); +var_dump(get_object_vars($obj)); +echo json_encode($obj); + +?> +--EXPECT-- +array(0) { +} +{"prop1":"bar","prop2":"foo"} diff --git a/Zend/zend_property_hooks.c b/Zend/zend_property_hooks.c index 0286bc0c4486f..82ddf2f8835a0 100644 --- a/Zend/zend_property_hooks.c +++ b/Zend/zend_property_hooks.c @@ -89,7 +89,8 @@ static zend_array *zho_build_properties_ex(zend_object *zobj, bool check_access, if (UNEXPECTED(Z_TYPE_P(OBJ_PROP(zobj, prop_info->offset)) == IS_UNDEF)) { HT_FLAGS(properties) |= HASH_FLAG_HAS_EMPTY_IND; } - zend_hash_update_ind(properties, property_name, OBJ_PROP(zobj, prop_info->offset)); + zval *tmp = zend_hash_lookup(properties, property_name); + ZVAL_INDIRECT(tmp, OBJ_PROP(zobj, prop_info->offset)); } skip_property: if (property_name != prop_info->name) {