Skip to content

Commit d23da75

Browse files
committed
Merge branch 'PHP-8.4' into PHP-8.5
* PHP-8.4: NEWS entries for recent SPL bug fixes ext/spl: ignore leading namespace separator in spl_autoload() (#22323) ext/spl: fix class_parents for classes with leading slash in non-autoload mode (#22283)
2 parents 403bf75 + 6a323eb commit d23da75

4 files changed

Lines changed: 103 additions & 11 deletions

File tree

NEWS

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,12 @@ PHP NEWS
3232
. Fixed bug GH-22324 (Ignore leading namespace separator in
3333
ReflectionParameter::__construct()). (jorgsowa)
3434

35+
- SPL:
36+
. Fix class_parents for classes with leading slash in non-autoload mode.
37+
(jorgsowa)
38+
. Ignore leading back-slash in class_parents(), class_implements(), and
39+
class_uses(). (jorgsowa)
40+
3541
- Standard:
3642
. Fixed bug GH-22395 (base_convert() outputs at most 64 characters).
3743
(Weilin Du)

ext/spl/php_spl.c

Lines changed: 7 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -43,16 +43,7 @@ ZEND_TLS HashTable *spl_autoload_functions;
4343

4444
static zend_class_entry * spl_find_ce_by_name(zend_string *name, bool autoload)
4545
{
46-
zend_class_entry *ce;
47-
48-
if (!autoload) {
49-
zend_string *lc_name = zend_string_tolower(name);
50-
51-
ce = zend_hash_find_ptr(EG(class_table), lc_name);
52-
zend_string_release(lc_name);
53-
} else {
54-
ce = zend_lookup_class(name);
55-
}
46+
zend_class_entry *ce = zend_lookup_class_ex(name, NULL, autoload ? 0 : ZEND_FETCH_CLASS_NO_AUTOLOAD);
5647
if (ce == NULL) {
5748
php_error_docref(NULL, E_WARNING, "Class %s does not exist%s", ZSTR_VAL(name), autoload ? " and could not be loaded" : "");
5849
return NULL;
@@ -310,7 +301,12 @@ PHP_FUNCTION(spl_autoload)
310301
pos_len = (int)ZSTR_LEN(file_exts);
311302
}
312303

313-
lc_name = zend_string_tolower(class_name);
304+
if (ZSTR_VAL(class_name)[0] == '\\') {
305+
lc_name = zend_string_alloc(ZSTR_LEN(class_name) - 1, 0);
306+
zend_str_tolower_copy(ZSTR_VAL(lc_name), ZSTR_VAL(class_name) + 1, ZSTR_LEN(class_name) - 1);
307+
} else {
308+
lc_name = zend_string_tolower(class_name);
309+
}
314310
while (pos && *pos && !EG(exception)) {
315311
pos1 = strchr(pos, ',');
316312
if (pos1) {
Lines changed: 72 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,72 @@
1+
--TEST--
2+
class_parents()/class_implements()/class_uses() accept a leading backslash regardless of $autoload
3+
--FILE--
4+
<?php
5+
6+
namespace {
7+
interface Iface {}
8+
trait Tr {}
9+
class ParentC implements Iface {}
10+
class ChildC extends ParentC {
11+
use Tr;
12+
}
13+
}
14+
15+
namespace MyNS {
16+
interface NSIface {}
17+
trait NSTr {}
18+
class NSParentC implements NSIface {}
19+
class NSChildC extends NSParentC {
20+
use NSTr;
21+
}
22+
}
23+
24+
namespace {
25+
26+
// The no-autoload path missed the leading-backslash strip before the fix.
27+
var_dump(class_parents('\ChildC', false));
28+
var_dump(class_parents('\ChildC'));
29+
var_dump(class_implements('\ParentC', false));
30+
var_dump(class_uses('\ChildC', false));
31+
32+
// Same for namespaced classes.
33+
var_dump(class_parents('\MyNS\NSChildC', false));
34+
var_dump(class_parents('\MyNS\NSChildC'));
35+
var_dump(class_implements('\MyNS\NSParentC', false));
36+
var_dump(class_uses('\MyNS\NSChildC', false));
37+
38+
}
39+
?>
40+
--EXPECT--
41+
array(1) {
42+
["ParentC"]=>
43+
string(7) "ParentC"
44+
}
45+
array(1) {
46+
["ParentC"]=>
47+
string(7) "ParentC"
48+
}
49+
array(1) {
50+
["Iface"]=>
51+
string(5) "Iface"
52+
}
53+
array(1) {
54+
["Tr"]=>
55+
string(2) "Tr"
56+
}
57+
array(1) {
58+
["MyNS\NSParentC"]=>
59+
string(14) "MyNS\NSParentC"
60+
}
61+
array(1) {
62+
["MyNS\NSParentC"]=>
63+
string(14) "MyNS\NSParentC"
64+
}
65+
array(1) {
66+
["MyNS\NSIface"]=>
67+
string(12) "MyNS\NSIface"
68+
}
69+
array(1) {
70+
["MyNS\NSTr"]=>
71+
string(9) "MyNS\NSTr"
72+
}
Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
--TEST--
2+
spl_autoload(): a leading "\" in the class name is ignored
3+
--FILE--
4+
<?php
5+
6+
set_include_path(__DIR__);
7+
spl_autoload_extensions(".inc");
8+
9+
spl_autoload("DualIterator");
10+
var_dump(class_exists("DualIterator", false));
11+
12+
spl_autoload("\\RecursiveDualIterator");
13+
var_dump(class_exists("RecursiveDualIterator", false));
14+
15+
?>
16+
--EXPECT--
17+
bool(true)
18+
bool(true)

0 commit comments

Comments
 (0)