Commit 63d183e9c1a for php

commit 63d183e9c1a12b5caa359c6af5885dea671d2f4a
Author: David Carlier <devnexen@gmail.com>
Date:   Sat Oct 31 06:45:08 2026 +0000

    ext/opcache: Fix JIT ignoring exceptions from typed property set hooks

    zend_may_throw_ex() didn't account for hooks on typed properties.

    Close GH-25075

diff --git a/NEWS b/NEWS
index 24fd78630de..a2550c672e1 100644
--- a/NEWS
+++ b/NEWS
@@ -81,6 +81,7 @@ PHP                                                                        NEWS
     loop-invariant addition). (Ilia Alshanetsky)
   . Fixed OSS-Fuzz #545352966 (default value AST of an SHM-persisted partial).
     (ndossche)
+  . Fixed JIT ignoring exceptions from typed property set hooks. (David Carlier)

 - PDO:
   . Fixed PDOStatement::getColumnMeta() reading out of bounds for an invalid
diff --git a/Zend/Optimizer/zend_inference.c b/Zend/Optimizer/zend_inference.c
index 04742707238..8d01ac050cf 100644
--- a/Zend/Optimizer/zend_inference.c
+++ b/Zend/Optimizer/zend_inference.c
@@ -5264,6 +5264,7 @@ ZEND_API bool zend_may_throw_ex(const zend_op *opline, const zend_ssa_op *ssa_op
 						 * and the value already has this type: the old value has no destructor.
 						 * If the property holds a reference, all its type sources accept this type because they accept the current value. */
 						if ((prop_info->flags & (ZEND_ACC_READONLY|ZEND_ACC_PPP_SET_MASK))
+						 || prop_info->hooks
 						 || ZEND_TYPE_IS_COMPLEX(prop_info->type)
 						 || (type_mask & ~(MAY_BE_NULL|MAY_BE_BOOL|MAY_BE_LONG|MAY_BE_DOUBLE|MAY_BE_STRING))
 						 /* single type, this excludes bool too as a reference can exist to true or false standalone types. */
diff --git a/ext/opcache/tests/jit/assign_obj_007.phpt b/ext/opcache/tests/jit/assign_obj_007.phpt
new file mode 100644
index 00000000000..3843b07e859
--- /dev/null
+++ b/ext/opcache/tests/jit/assign_obj_007.phpt
@@ -0,0 +1,44 @@
+--TEST--
+JIT ASSIGN_OBJ: exception thrown by a set hook on a typed property
+--INI--
+opcache.enable=1
+opcache.enable_cli=1
+opcache.file_update_protection=0
+opcache.jit_buffer_size=1M
+opcache.jit=tracing
+opcache.jit_hot_loop=1
+opcache.jit_hot_func=1
+opcache.jit_hot_return=1
+opcache.jit_hot_side_exit=1
+--FILE--
+<?php
+class Foo {
+    public int $test = 1 {
+        set(int $v) {
+            if ($v === 3) {
+                throw new Exception('hook threw');
+            }
+            $this->test = $v;
+        }
+    }
+}
+
+function test() {
+    $foo = new Foo;
+    for ($i = 0; $i < 10; $i++) {
+        $foo->test = $i;
+        echo $i, PHP_EOL;
+    }
+}
+
+try {
+    test();
+} catch (Exception $e) {
+    echo $e::class, ': ', $e->getMessage(), PHP_EOL;
+}
+?>
+--EXPECT--
+0
+1
+2
+Exception: hook threw