[PHP-CVS] [php-src] master: Merge branch 'PHP-8.4' into PHP-8.5

[email protected] (Ilia Alshanetsky) Thu, 30 Jul 2026 12:49:15 +0000
Newsgroups php.cvs
Message-ID <[email protected]>
Author: Ilia Alshanetsky (iliaal)
Date: 2026-07-30T08:24:47-04:00

Commit: https://github.com/php/php-src/commit/8c5e258a0079b739f844e3ea9808afba518bc34d
Raw diff: https://github.com/php/php-src/commit/8c5e258a0079b739f844e3ea9808afba518bc34d.diff

Merge branch 'PHP-8.4' into PHP-8.5

* PHP-8.4:
  Free the hooked property value when json_encode() sees an exception

Changed paths:
  A  ext/json/tests/json_encode_hooked_property_throwing_getter.phpt
  M  ext/json/json_encoder.c


Diff:

diff --git a/ext/json/json_encoder.c b/ext/json/json_encoder.c
index a73277915405..d6da2e5651af 100644
--- a/ext/json/json_encoder.c
+++ b/ext/json/json_encoder.c
@@ -272,6 +272,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--
+<?php
+
+class Value
+{
+    public function __destruct()
+    {
+        echo "Value::__destruct\n";
+    }
+}
+
+class ThrowOnFree
+{
+    public function __destruct()
+    {
+        throw new Exception('thrown while freeing the get hook frame');
+    }
+}
+
+class Container
+{
+    public $hooked {
+        get {
+            $local = new ThrowOnFree();
+            return new Value();
+        }
+    }
+}
+
+try {
+    json_encode(new Container());
+} catch (Throwable $e) {
+    echo $e::class, ': ', $e->getMessage(), "\n";
+}
+
+echo "done\n";
+
+?>
+--EXPECT--
+Value::__destruct
+Exception: thrown while freeing the get hook frame
+done