Commit 7f4e0f4b72e for php.net
commit 7f4e0f4b72e392ec55497b01808064fb3605329a
Author: Jorg Adam Sowa <jorg.sowa@gmail.com>
Date: Wed Jun 24 12:44:04 2026 +0200
ext/spl: fix class_parents for classes with leading slash in non-autoload mode (#22283)
Fixes GH-22282
diff --git a/ext/spl/php_spl.c b/ext/spl/php_spl.c
index 78315e9880b..24cd66db445 100644
--- a/ext/spl/php_spl.c
+++ b/ext/spl/php_spl.c
@@ -43,16 +43,7 @@ ZEND_TLS HashTable *spl_autoload_functions;
static zend_class_entry * spl_find_ce_by_name(zend_string *name, bool autoload)
{
- zend_class_entry *ce;
-
- if (!autoload) {
- zend_string *lc_name = zend_string_tolower(name);
-
- ce = zend_hash_find_ptr(EG(class_table), lc_name);
- zend_string_release(lc_name);
- } else {
- ce = zend_lookup_class(name);
- }
+ zend_class_entry *ce = zend_lookup_class_ex(name, NULL, autoload ? 0 : ZEND_FETCH_CLASS_NO_AUTOLOAD);
if (ce == NULL) {
php_error_docref(NULL, E_WARNING, "Class %s does not exist%s", ZSTR_VAL(name), autoload ? " and could not be loaded" : "");
return NULL;
diff --git a/ext/spl/tests/class_parents_leading_backslash.phpt b/ext/spl/tests/class_parents_leading_backslash.phpt
new file mode 100644
index 00000000000..be538b79db9
--- /dev/null
+++ b/ext/spl/tests/class_parents_leading_backslash.phpt
@@ -0,0 +1,72 @@
+--TEST--
+class_parents()/class_implements()/class_uses() accept a leading backslash regardless of $autoload
+--FILE--
+<?php
+
+namespace {
+ interface Iface {}
+ trait Tr {}
+ class ParentC implements Iface {}
+ class ChildC extends ParentC {
+ use Tr;
+ }
+}
+
+namespace MyNS {
+ interface NSIface {}
+ trait NSTr {}
+ class NSParentC implements NSIface {}
+ class NSChildC extends NSParentC {
+ use NSTr;
+ }
+}
+
+namespace {
+
+// The no-autoload path missed the leading-backslash strip before the fix.
+var_dump(class_parents('\ChildC', false));
+var_dump(class_parents('\ChildC'));
+var_dump(class_implements('\ParentC', false));
+var_dump(class_uses('\ChildC', false));
+
+// Same for namespaced classes.
+var_dump(class_parents('\MyNS\NSChildC', false));
+var_dump(class_parents('\MyNS\NSChildC'));
+var_dump(class_implements('\MyNS\NSParentC', false));
+var_dump(class_uses('\MyNS\NSChildC', false));
+
+}
+?>
+--EXPECT--
+array(1) {
+ ["ParentC"]=>
+ string(7) "ParentC"
+}
+array(1) {
+ ["ParentC"]=>
+ string(7) "ParentC"
+}
+array(1) {
+ ["Iface"]=>
+ string(5) "Iface"
+}
+array(1) {
+ ["Tr"]=>
+ string(2) "Tr"
+}
+array(1) {
+ ["MyNS\NSParentC"]=>
+ string(14) "MyNS\NSParentC"
+}
+array(1) {
+ ["MyNS\NSParentC"]=>
+ string(14) "MyNS\NSParentC"
+}
+array(1) {
+ ["MyNS\NSIface"]=>
+ string(12) "MyNS\NSIface"
+}
+array(1) {
+ ["MyNS\NSTr"]=>
+ string(9) "MyNS\NSTr"
+}