Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 5 additions & 0 deletions NEWS
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,11 @@ PHP NEWS
. Fixed bug GH-21314 (Different session garbage collector behavior between
PHP 8.3 and PHP 8.5). (jorgsowa)

- SPL:
. spl_autoload() now builds the include file name from the case-preserved
class name instead of lowercasing it, fixing autoloading of classes with
non-lowercase names on case-sensitive file systems. (jorgsowa)

- Streams:
. Fixed bug GH-21468 (Segfault in file_get_contents w/ a https URL
and a proxy set). (CVE-2026-12184) (ndossche)
Expand Down
4 changes: 4 additions & 0 deletions UPGRADING
Original file line number Diff line number Diff line change
Expand Up @@ -164,6 +164,10 @@ PHP 8.6 UPGRADE NOTES
. SplFileObject::next() past EOF no longer increments key() without bound.
SplFileObject::seek() past EOF now produces the same key() value as
SplTempFileObject; the two previously returned different values.
. The default spl_autoload() implementation now builds the include file
name from the case-preserved class name instead of its lowercased form.
On case-sensitive file systems the file name must match the class name
casing (e.g. MyClass.php instead of myclass.php).

- Standard:
. Form feed (\f) is now added in the default trimmed characters of trim(),
Expand Down
22 changes: 11 additions & 11 deletions ext/spl/php_spl.c
Original file line number Diff line number Diff line change
Expand Up @@ -249,14 +249,14 @@ PHP_FUNCTION(spl_classes)
}
/* }}} */

static bool spl_autoload(zend_string *lc_name, const char *ext, size_t ext_len) /* {{{ */
static bool spl_autoload(const char *name, size_t name_len, const char *ext, size_t ext_len) /* {{{ */
{
zend_string *class_file;
zval dummy;
zend_file_handle file_handle;
zval result;

class_file = zend_string_concat2(ZSTR_VAL(lc_name), ZSTR_LEN(lc_name), ext, ext_len);
class_file = zend_string_concat2(name, name_len, ext, ext_len);

#if DEFAULT_SLASH != '\\'
{
Expand Down Expand Up @@ -294,7 +294,7 @@ static bool spl_autoload(zend_string *lc_name, const char *ext, size_t ext_len)
efree(new_op_array);
zval_ptr_dtor(&result);

ret = zend_hash_exists(EG(class_table), lc_name);
ret = zend_hash_str_find_ptr_lc(EG(class_table), name, name_len) != NULL;
}
}
zend_destroy_file_handle(&file_handle);
Expand All @@ -307,7 +307,7 @@ PHP_FUNCTION(spl_autoload)
{
size_t pos_len, pos1_len;
char *pos, *pos1;
zend_string *class_name, *lc_name, *file_exts = NULL;
zend_string *class_name, *file_exts = NULL;

if (zend_parse_parameters(ZEND_NUM_ARGS(), "S|S!", &class_name, &file_exts) == FAILURE) {
RETURN_THROWS();
Expand All @@ -325,26 +325,26 @@ PHP_FUNCTION(spl_autoload)
pos_len = ZSTR_LEN(file_exts);
}

if (ZSTR_VAL(class_name)[0] == '\\') {
lc_name = zend_string_alloc(ZSTR_LEN(class_name) - 1, 0);
zend_str_tolower_copy(ZSTR_VAL(lc_name), ZSTR_VAL(class_name) + 1, ZSTR_LEN(class_name) - 1);
} else {
lc_name = zend_string_tolower(class_name);
const char *name = ZSTR_VAL(class_name);
size_t name_len = ZSTR_LEN(class_name);
if (*name == '\\') {
name++;
name_len--;
}

while (pos && *pos && !EG(exception)) {
pos1 = strchr(pos, ',');
if (pos1) {
pos1_len = (size_t)(pos1 - pos);
} else {
pos1_len = pos_len;
}
if (spl_autoload(lc_name, pos, pos1_len)) {
if (spl_autoload(name, name_len, pos, pos1_len)) {
break; /* loaded */
}
pos = pos1 ? pos1 + 1 : NULL;
pos_len = pos1? pos_len - pos1_len - 1 : 0;
}
zend_string_release(lc_name);
} /* }}} */

/* {{{ Register and return default file extensions for spl_autoload */
Expand Down
File renamed without changes.
8 changes: 4 additions & 4 deletions ext/spl/tests/autoloading/spl_autoload_001.phpt
Original file line number Diff line number Diff line change
Expand Up @@ -74,15 +74,15 @@ try {
--EXPECTF--
===EMPTY===
string(9) ".inc,.php"
%stestclass.inc
%sTestClass.inc
Class TestClass could not be loaded
===()===
Class TestClass could not be loaded
===(1)===
Class TestClass could not be loaded
===(.inc,,.php.inc)===
%stestclass
%stestclass.php.inc
%sTestClass
%sTestClass.php.inc
Class TestClass could not be loaded
===()===
Class TestClass could not be loaded
Expand All @@ -97,7 +97,7 @@ bool(false)
===LOAD===
TestFunc1(TestClass)
TestFunc2(TestClass)
%stestclass.class.inc
%sTestClass.class.inc
bool(true)
===NOFUNCTION===
spl_autoload_register(): Argument #1 ($callback) must be a valid callback or null, function "unavailable_autoload_function" not found or invalid function name
6 changes: 3 additions & 3 deletions ext/spl/tests/autoloading/spl_autoload_009.phpt
Original file line number Diff line number Diff line change
Expand Up @@ -14,10 +14,10 @@ function my_autoload($name)
spl_autoload_register("spl_autoload");
spl_autoload_register("my_autoload");

$obj = new testclass;
$obj = new TestClass;

?>
--EXPECTF--
%stestclass.inc
%stestclass.class.inc
%sTestClass.inc
%sTestClass.class.inc
bool(true)
4 changes: 2 additions & 2 deletions ext/spl/tests/autoloading/spl_autoload_call_basic.phpt
Original file line number Diff line number Diff line change
Expand Up @@ -6,13 +6,13 @@ Jean-Marc Fontaine <jean-marc.fontaine@alterway.fr>
--FILE--
<?php
function customAutolader($class) {
require_once __DIR__ . '/testclass.class.inc';
require_once __DIR__ . '/TestClass.class.inc';
}
spl_autoload_register('customAutolader');

spl_autoload_call('TestClass');
var_dump(class_exists('TestClass', false));
?>
--EXPECTF--
%stestclass.class.inc
%sTestClass.class.inc
bool(true)
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ spl_autoload_register() function - warn when using false as second argument for
--FILE--
<?php
function customAutolader($class) {
require_once __DIR__ . '/testclass.class.inc';
require_once __DIR__ . '/TestClass.class.inc';
}
spl_autoload_register('customAutolader', false);

Expand All @@ -12,5 +12,5 @@ var_dump(class_exists('TestClass', false));
?>
--EXPECTF--
Notice: spl_autoload_register(): Argument #2 ($do_throw) has been ignored, spl_autoload_register() will always throw in %s on line %d
%stestclass.class.inc
%sTestClass.class.inc
bool(true)
2 changes: 1 addition & 1 deletion ext/spl/tests/dualiterator_001.phpt
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ SPL: DualIterator

function spl_examples_autoload($classname)
{
include(__DIR__ . '/' . strtolower($classname) . '.inc');
include(__DIR__ . '/' . $classname . '.inc');
}

spl_autoload_register('spl_examples_autoload');
Expand Down