From 9de3544c0cce7ed053839a586102261eefde1487 Mon Sep 17 00:00:00 2001 From: Ilia Alshanetsky Date: Wed, 29 Jul 2026 07:28:39 -0400 Subject: [PATCH] Free the hooked property value when json_encode() sees an exception php_json_encode_array() reads a hooked property into a local zval and bails out when an exception is pending. The get hook can publish its return value into that zval and then throw while its frame is freed, for example from the destructor of one of its locals, so the bailout leaks the value until request shutdown. Destroy it on the way out, the way the other failure exit already does. Closes GH-22919 --- ext/json/json_encoder.c | 1 + ...ncode_hooked_property_throwing_getter.phpt | 44 +++++++++++++++++++ 2 files changed, 45 insertions(+) create mode 100644 ext/json/tests/json_encode_hooked_property_throwing_getter.phpt diff --git a/ext/json/json_encoder.c b/ext/json/json_encoder.c index 4145bc2b6154..cefee25de90a 100644 --- a/ext/json/json_encoder.c +++ b/ext/json/json_encoder.c @@ -287,6 +287,7 @@ static zend_result php_json_encode_array(smart_str *buf, zval *val, int options, if (EG(exception)) { PHP_JSON_HASH_UNPROTECT_RECURSION(recursion_rc); zend_release_properties(prop_ht); + zval_ptr_dtor(&tmp); return FAILURE; } } diff --git a/ext/json/tests/json_encode_hooked_property_throwing_getter.phpt b/ext/json/tests/json_encode_hooked_property_throwing_getter.phpt new file mode 100644 index 000000000000..63fc8cf42c0e --- /dev/null +++ b/ext/json/tests/json_encode_hooked_property_throwing_getter.phpt @@ -0,0 +1,44 @@ +--TEST-- +json_encode() releases the hooked property value when the get hook throws +--FILE-- +getMessage(), "\n"; +} + +echo "done\n"; + +?> +--EXPECT-- +Value::__destruct +Exception: thrown while freeing the get hook frame +done