Commit b3a8e07fe56 for php

commit b3a8e07fe561f8300ba7a68c10a3bfd75ccdcf7a
Author: Nicolas Grekas <nicolas.grekas@gmail.com>
Date:   Sun Nov 8 04:32:05 2026 +0000

    Fix use-after-free in zend_compile_const_decl() under opcache (#25302)

    When compiling a constant declaration with OPcache, the first interning
    attempt may miss a string that another thread or process adds to shared
    memory before the constant name is interned again for ZEND_DECLARE_CONST.
    The second attempt then releases the original string, leaving
    zend_register_seen_symbol() to read and addref freed memory.

    Register the constant as a seen symbol before passing its name to the
    literal so that the symbol table keeps the string alive during interning.
    The race was observed with FrankenPHP when restarting workers that compile
    the same files concurrently against fresh shared memory.

    Closes #25302

diff --git a/NEWS b/NEWS
index 9ae8c7add12..a84629e1877 100644
--- a/NEWS
+++ b/NEWS
@@ -16,6 +16,8 @@ PHP                                                                        NEWS
     hooked subclass). (Lazizbek Ergashev)
   . Fixed bug GH-25299 (Exception string code is lost after unserialize()).
     (Lazizbek Ergashev, David Carlier)
+  . Fixed bug GH-25302 (Use-after-free in zend_compile_const_decl() with
+    OPcache during concurrent compilation). (Nicolas Grekas)

 - Curl:
   . Fixed curl_reset() retaining CURLOPT_PRIVATE after reset. (lacatoire)
diff --git a/Zend/zend_compile.c b/Zend/zend_compile.c
index 7e7e602f589..d3538a240a7 100644
--- a/Zend/zend_compile.c
+++ b/Zend/zend_compile.c
@@ -9483,12 +9483,15 @@ static void zend_compile_const_decl(zend_ast *ast) /* {{{ */
 			}
 		}

+		/* Register before the literal takes the name: interning it there may
+		 * release it, when opcache has put the same string in shared memory
+		 * since the call above. */
+		zend_register_seen_symbol(name, ZEND_SYMBOL_CONST);
+
 		name_node.op_type = IS_CONST;
 		ZVAL_STR(&name_node.u.constant, name);

 		zend_emit_op(NULL, ZEND_DECLARE_CONST, &name_node, &value_node);
-
-		zend_register_seen_symbol(name, ZEND_SYMBOL_CONST);
 	}
 }
 /* }}}*/