Commit 4b4ba03b67d for php.net

commit 4b4ba03b67d8abed9cc4ef1be3cc8b5cf75b8c9c
Author: Jérôme Tamarelle <jerome@tamarelle.net>
Date:   Fri Apr 17 22:39:32 2026 +0200

    gen_stub: fix invalid C variable name for namespaced types in union/intersection type list (#21717)

    When generating a union or intersection type list with multiple class
    types, the variable holding each zend_string* was declared using
    toVarEscapedName() (backslashes replaced by underscores), but the
    subsequent ZEND_TYPE_INIT_CLASS() reference used toEscapedName()
    (backslashes escaped as \\), producing an invalid C identifier.

diff --git a/build/gen_stub.php b/build/gen_stub.php
index ce1a2386661..c189abd0347 100755
--- a/build/gen_stub.php
+++ b/build/gen_stub.php
@@ -2375,8 +2375,8 @@ protected function getTypeCode(string $variableLikeName, string &$code): string
                     $code .= "\t{$variableLikeType}_{$variableLikeName}_type_list->num_types = $classTypeCount;\n";

                     foreach ($arginfoType->classTypes as $k => $classType) {
-                        $escapedClassName = $classType->toEscapedName();
-                        $code .= "\t{$variableLikeType}_{$variableLikeName}_type_list->types[$k] = (zend_type) ZEND_TYPE_INIT_CLASS({$variableLikeType}_{$variableLikeName}_class_{$escapedClassName}, 0, 0);\n";
+                        $varEscapedClassName = $classType->toVarEscapedName();
+                        $code .= "\t{$variableLikeType}_{$variableLikeName}_type_list->types[$k] = (zend_type) ZEND_TYPE_INIT_CLASS({$variableLikeType}_{$variableLikeName}_class_{$varEscapedClassName}, 0, 0);\n";
                     }

                     $typeMaskCode = $this->type->toArginfoType()->toTypeMask();
diff --git a/ext/zend_test/test.c b/ext/zend_test/test.c
index 02252a2d43e..96f8db83c11 100644
--- a/ext/zend_test/test.c
+++ b/ext/zend_test/test.c
@@ -65,6 +65,7 @@ static zend_class_entry *zend_test_forbid_dynamic_call;
 static zend_class_entry *zend_test_ns_foo_class;
 static zend_class_entry *zend_test_ns_unlikely_compile_error_class;
 static zend_class_entry *zend_test_ns_not_unlikely_compile_error_class;
+static zend_class_entry *zend_test_ns_bar_class;
 static zend_class_entry *zend_test_ns2_foo_class;
 static zend_class_entry *zend_test_ns2_ns_foo_class;
 static zend_class_entry *zend_test_unit_enum;
@@ -1567,6 +1568,7 @@ PHP_MINIT_FUNCTION(zend_test)
 	zend_test_ns_foo_class = register_class_ZendTestNS_Foo();
 	zend_test_ns_unlikely_compile_error_class = register_class_ZendTestNS_UnlikelyCompileError();
 	zend_test_ns_not_unlikely_compile_error_class = register_class_ZendTestNS_NotUnlikelyCompileError();
+	zend_test_ns_bar_class = register_class_ZendTestNS_Bar();
 	zend_test_ns2_foo_class = register_class_ZendTestNS2_Foo();
 	zend_test_ns2_ns_foo_class = register_class_ZendTestNS2_ZendSubNS_Foo();

diff --git a/ext/zend_test/test.stub.php b/ext/zend_test/test.stub.php
index e102082c6a9..f4844eb0681 100644
--- a/ext/zend_test/test.stub.php
+++ b/ext/zend_test/test.stub.php
@@ -363,6 +363,8 @@ class Foo {
         public function method(): int {}
     }

+    interface Bar {}
+
     class UnlikelyCompileError {
         /* This method signature would create a compile error due to the string
          * "ZendTestNS\UnlikelyCompileError" in the generated macro call */
@@ -383,6 +385,8 @@ public function method(): ?NotUnlikelyCompileError {}

     class Foo {
         public ZendSubNS\Foo $foo;
+        public ZendSubNS\Foo&\ZendTestNS\Bar $intersectionProp;
+        public ZendSubNS\Foo|\ZendTestNS\Bar $unionProp;

         public function method(): void {}
     }
diff --git a/ext/zend_test/test_arginfo.h b/ext/zend_test/test_arginfo.h
index 30297234fc8..d2bdbd72db4 100644
Binary files a/ext/zend_test/test_arginfo.h and b/ext/zend_test/test_arginfo.h differ
diff --git a/ext/zend_test/test_decl.h b/ext/zend_test/test_decl.h
index ed0874f51e7..816e03919a1 100644
Binary files a/ext/zend_test/test_decl.h and b/ext/zend_test/test_decl.h differ
diff --git a/ext/zend_test/test_legacy_arginfo.h b/ext/zend_test/test_legacy_arginfo.h
index 3dcdad8ff6c..b4a07503ad0 100644
Binary files a/ext/zend_test/test_legacy_arginfo.h and b/ext/zend_test/test_legacy_arginfo.h differ
diff --git a/ext/zend_test/tests/gen_stub_test_01.phpt b/ext/zend_test/tests/gen_stub_test_01.phpt
index 0f5d525322d..3126eb61631 100644
--- a/ext/zend_test/tests/gen_stub_test_01.phpt
+++ b/ext/zend_test/tests/gen_stub_test_01.phpt
@@ -18,11 +18,19 @@
 object(ZendTestNS2\Foo)#%d (%d) {
   ["foo"]=>
   uninitialized(ZendTestNS2\ZendSubNS\Foo)
+  ["intersectionProp"]=>
+  uninitialized(ZendTestNS2\ZendSubNS\Foo&ZendTestNS\Bar)
+  ["unionProp"]=>
+  uninitialized(ZendTestNS2\ZendSubNS\Foo|ZendTestNS\Bar)
 }
 object(ZendTestNS2\Foo)#%d (%d) {
   ["foo"]=>
   object(ZendTestNS2\ZendSubNS\Foo)#%d (%d) {
   }
+  ["intersectionProp"]=>
+  uninitialized(ZendTestNS2\ZendSubNS\Foo&ZendTestNS\Bar)
+  ["unionProp"]=>
+  uninitialized(ZendTestNS2\ZendSubNS\Foo|ZendTestNS\Bar)
 }
 object(ZendTestNS\UnlikelyCompileError)#%d (%d) {
 }